Some enhancement proposals

28 views
Skip to first unread message

Alan Franzoni

unread,
Nov 4, 2010, 7:25:34 AM11/4/10
to python-...@googlegroups.com
Hello everybody,
I did not know about this mailing list and I had sent some improvement
proposals to Tarek about the python keyring module via private email.

Some I've already implemented on a fork we're currently using at work,
mostly for mercurial keyring integration; I'm willing to help and
contribute them.

Here's a resume along with Tarek's own comments.

Maintenance proposals:

Alan:

- don't always do the "automagic" keyring selection - client code must
be free too choose its backend implementation if it really wants to;
automatic keyring discovery should be done via a factory function that
can be called explicitly.
- separate keyring instantiation from usage through a factory, be it a
class or static method - we shouldn't require keyring instantiation
just to check if it could work.


Tarek comments:

1) Automagic should be the default behavior. If the user wants to use a
specific backend, he should be able to do it by configuration.
I think that's already the case.
2) Like, a factory that returns a backend?


R:
My idea is to use a factory like get_configured_keyring which would
just perform the very same as it is currently done automatically at
import time.
Also, I'd like a factory method for each backend which can just raise
an exception if the backend is unavailable on such platform or return
the instantiated backend if it's available and working.

this way if client code really wants to use a specific keyring backend
(for whatever reason), that's possibile, and there's no issue with the
need to check the "supported" property - either the backend is
available and working, and we get an instance of it, or we get an
exception we know we must intercept.
Also, the preferred order for get_configured_keyring() when multiple
backends are available should be a separate concern, it seems to me
pretty undeterministic at the present time - what happens if both KDE
and Gnome keyring are available on the system?

Alan:

- Create an "helper" class that allows getting/setting password
without getting an exception;


Tarek:

How ? with a fallback on another backend ?


R:
This is an hint from another user:

http://bitbucket.org/kang/python-keyring-lib/issue/32/error-on-keyring-password-get-set-shouldnt-disrupt-user

Whenever I set a password to a keyring, I might or might want to be
notified of errors in my client code. If I can't set a password, I
might just want to go on without saving it. If I can't retrieve a
password, I'd probably want to ask the user for it.

benji_york , on the contrary, says this should be dealt with in client
code, and he's got a point.

What I'd like to is:

- make behaviour consistent across all keyring backends, so that when
getting I password, I can distinguish between "password is unavailable
in the keyring" or "keyring access failed for some reason", and when
writing passwords I always get an exception if I couldn't save
passwords
- add a ForgivingKeyringProxy (or something like that) that just
ignores exceptions from pw getter/setter if I don't want to handle it
in client code. Many times I'd just want to ignore it in my code and
just go on as if it I didn't have a keyring, and forcing the client to
write a lot of boilerplate is not something that could encourage the
usage of a library.

Alan:

- improve unit test coverage and separate integration tests (there're
some tests using the *real* keyring!) from unit tests.

Tarek:

yeah, tests are to be improved.


Other improvements I propose:

- directly include some application stacks as long as they're small
enough; mercurial_keyring could be included as a module
(keyring.stacks.mercurial?) without requiring a separate extension.

And I've been told there're updated packages built for Debian and
Ubuntu; were can I find them? I found those on launchpad:

https://launchpad.net/~kupfer-team/+archive/ppa

But it's a fairly old version.

--
Alan Franzoni
--
contact me at public@[mysurname].eu

Tarek Ziadé

unread,
Nov 4, 2010, 10:15:46 PM11/4/10
to python-...@googlegroups.com
On Thu, Nov 4, 2010 at 12:25 PM, Alan Franzoni <mai...@franzoni.eu> wrote:
[..]

>
> R:
> My idea is to use a factory like get_configured_keyring which would
> just perform the very same as it is currently done automatically at
> import time.
> Also, I'd like a factory method for each backend which can just raise
> an exception if the backend is unavailable on such platform or return
> the instantiated backend if it's available and working.

You can call keyring.backend.get_all_keyring() and see if the backend
you want to use is supported by calling supported()

It's up to the keyring to return the right value when supported is
called, if the platform is not supported.

We could also add a get_keyring(name) API to avoid looping.

I am not sure to understand why you want to change this model, and why
you want to raise an exception. How this will be better ?

> this way if client code really wants to use a specific keyring backend
> (for whatever reason), that's possibile, and there's no issue with the
> need to check the "supported" property - either the backend is
> available and working, and we get an instance of it, or we get an
> exception we know we must intercept

What's wrong with checking the supported property. Why catching an
error would be better ?

> Also, the preferred order for get_configured_keyring() when multiple
> backends are available should be a separate concern, it seems to me
> pretty undeterministic at the present time - what happens if both KDE
> and Gnome keyring are available on the system?

One of them is picked first, since they have the same weight. There's
no other way to do it automatically, I think.


>
> R:
> This is an hint from another user:
>
> http://bitbucket.org/kang/python-keyring-lib/issue/32/error-on-keyring-password-get-set-shouldnt-disrupt-user
>
> Whenever I set a password to a keyring, I might or might want to be
> notified of errors in my client code. If I can't set a password, I
> might just want to go on without saving it. If I can't retrieve a
> password, I'd probably want to ask the user for it.
>
> benji_york , on the contrary, says this should be dealt with in client
> code, and he's got a point.

I am with benji here

>  What I'd like to is:
>
> - make behaviour consistent across all keyring backends, so that  when
> getting I password, I can distinguish between "password is unavailable
> in the keyring" or "keyring access failed for some reason", and when
> writing passwords I always get an exception if I couldn't save
> passwords

any failure should raise an exception. get_password() returns None
when the password does not exists.
Do we have a backend that does not do this ? I did a quick scan and it seems not


> - add a ForgivingKeyringProxy (or something like that) that just
> ignores exceptions from pw getter/setter if I don't want to handle it
> in client code. Many times I'd just want to ignore it in my code and
> just go on as if it I didn't have a keyring, and forcing the client to
> write a lot of boilerplate is not something that could encourage the
> usage of a library.

I am -1 on this: ignoring errors is a very specific behavior that
should be handled by the client application if it wishes to silence
it. For the keyring lib, failing to set a password is a failure and
needs to be raised.

...


>
> And I've been told there're updated packages built for Debian and
> Ubuntu; were can I find them? I found those on launchpad:
>
> https://launchpad.net/~kupfer-team/+archive/ppa
>
> But it's a fairly old version.

What I meant was that keyring is already packaged in Debian and Ubuntu, by Carl.

Cheers
Tarek


--
Tarek Ziadé | http://ziade.org

Alan Franzoni

unread,
Nov 5, 2010, 6:40:36 AM11/5/10
to python-...@googlegroups.com
On Fri, Nov 5, 2010 at 3:15 AM, Tarek Ziadé <ziade...@gmail.com> wrote:
> You can call keyring.backend.get_all_keyring() and see if the backend
> you want to use is supported by calling supported()

I don't think it's a good approach. I've got an instance of a class,
but I must call a method just to see if I can use it. The supported()
method has nothing to do with the object interface itself - it's
really a system-wide property, a keyring backend is either supported
or it isn't. It is not possible to instance two keyring instances for
the same backend and have one to be supported and the other not.

The usual contract is that, whenever an object is successfully
constructed, it can be used. It would be a rather messy experience if
that weren't the rule. Of course the keyring lib is rather small, but
I don't see why this practice should be avoided.

On the contrary, using a factory would be much cleaner - either the
object is instanced, and hence it's usable, or the factory raises an
exception.

Also, supported() does two things: both says whether that backend
works on the system, and tells whether it's a "preferred" backend.
This ties two different concerns in a single method.

> What's wrong with checking the supported property. Why catching an
> error would be better ?

We may want to return None from the factory instead of raising an
Exception, but the point is: constructing an instance that doesn't
work is not a good practice.

>> Also, the preferred order for get_configured_keyring() when multiple
>> backends are available should be a separate concern, it seems to me
>> pretty undeterministic at the present time - what happens if both KDE
>> and Gnome keyring are available on the system?
>
> One of them is picked first, since they have the same weight. There's
> no other way to do it automatically, I think.

We might resort to lexicographical order whenever the weight is the same.
>> R:


>> Whenever I set a password to a keyring, I might or might want to be
>> notified of errors in my client code. If I can't set a password, I
>> might just want to go on without saving it. If I can't retrieve a
>> password, I'd probably want to ask the user for it.

> I am with benji here

> any failure should raise an exception. get_password() returns None


> when the password does not exists.
> Do we have a backend that does not do this ? I did a quick scan and it seems not

I was probably wrong about that about backends.

>> - add a ForgivingKeyringProxy (or something like that) that just
>> ignores exceptions from pw getter/setter if I don't want to handle it
>> in client code. Many times I'd just want to ignore it in my code and
>> just go on as if it I didn't have a keyring, and forcing the client to
>> write a lot of boilerplate is not something that could encourage the
>> usage of a library.
>
> I am -1 on this: ignoring errors is a very specific behavior that
> should be handled by the client application if it wishes to silence
> it. For the keyring lib, failing to set a password is a failure and
> needs to be raised.

I mean: let's add a ForgivingKeyringProxy in the keyring library as an
optional wrapper class, and let any client code to use it if it wants
to, otherwise just leave the default behaviour as it is. It's just
that I think the case is frequent enough to deserve an helper class,
without forcing users to re-code their exception-ignore

Alan Franzoni

unread,
Nov 12, 2010, 12:42:53 PM11/12/10
to python-...@googlegroups.com
Ping.

Any further comment on that? I'd be glad to contribute once we decide
where should we go.

Marcin Kasperski

unread,
Nov 12, 2010, 3:49:52 PM11/12/10
to python-...@googlegroups.com
My 2 cents (which mostly agree with Alan but rephrase it a bit differently):

a) I feel that the whole logic of picking the appropriate keyring is
too simplistic. Not all supported keyrings are equal, when I work on
Linux under X11, Gnome Keyring is supported, KDE Wallet is suported,
encrypted file is supported and plain file is supported, still - there
are clear priorities (which moreover are different depending on
desktop environment I use). It would be great if there were some logic
to accomodate this (like differentiating "I work" from "I work and I
am preferred backend here"). I tried working on some patch towards
this in the past but failed to find natural api, still I support the
feeling that we have a problem here

b) I agree with Alan that it would be more natural to separate
question "which keyrings may work" from creating them.

Alan Franzoni

unread,
Nov 15, 2010, 6:00:00 AM11/15/10
to python-...@googlegroups.com
On Fri, Nov 12, 2010 at 9:49 PM, Marcin Kasperski
<Marcin.K...@mekk.waw.pl>

> a) I feel that the whole logic of picking the appropriate keyring is
> too simplistic. Not all supported keyrings are equal, when I work on

Yes, it's not an easy task to accomplish. keyring is mostly an
"automatic wrapper" library, which might support various and different
backends. Now it tries to do something that "just works" but might
just not work - or might just not work every time.

Maybe it's better to force the user to configure it the first time and
then forget about it, and just fulfill the python karma "In the face
of ambiguity, refuse the temptation to guess." ?

Marcin Kasperski

unread,
Nov 15, 2010, 6:39:24 AM11/15/10
to python-...@googlegroups.com
>> a) I feel that the whole logic of picking the appropriate keyring is
>> too simplistic. Not all supported keyrings are equal, when I work on
>
> Yes, it's not an easy task to accomplish. keyring is mostly an
> "automatic wrapper" library, which might support various and different
> backends. Now it tries to do something that "just works" but might
> just not work - or might just not work every time.
>
> Maybe it's better to force the user to configure it the first time and
> then forget about it, and just fulfill the python karma "In the face
> of ambiguity, refuse the temptation to guess." ?

I don't find this idea to be too cute. After all firefox, evolution,
etc etc don't ask where to save the passwords. This is techie detail.

All realistic scenarios I can think about could be solved by bare
extension from "supported/unsupported" to "supported and
native/supported/unsupported". Although some notion of "priority"
could probably be easier to maintain in the long term.

Tarek Ziadé

unread,
Nov 15, 2010, 6:46:33 AM11/15/10
to python-...@googlegroups.com
Sorry for the late replies, been busy

On Fri, Nov 12, 2010 at 9:49 PM, Marcin Kasperski

<Marcin.K...@mekk.waw.pl> wrote:
> My 2 cents (which mostly agree with Alan but rephrase it a bit differently):
>
> a) I feel that the whole logic of picking the appropriate keyring is
> too simplistic. Not all supported keyrings are equal, when I work on
> Linux under X11, Gnome Keyring is supported, KDE Wallet is suported,
> encrypted file is supported and plain file is supported, still - there
> are clear priorities (which moreover are different depending on
> desktop environment I use). It would be great if there were some logic
> to accomodate this (like differentiating "I work" from "I work and I
> am preferred backend here"). I tried working on some patch towards
> this in the past but failed to find natural api, still I support the
> feeling that we have a problem here

I think there are two user stories:

1/ a user install the keyring and wants it to work. the keyring select
one specific backend, and always the same, even if several backends
are supported on the platform. ISTM that what we have fulfils this.

2/ a power user that wants to define which one he wants to use. He can
do so via configuration.


>
> b) I agree with Alan that it would be more natural to separate
> question "which keyrings may work" from creating them.

The current logic is to have this code locate in the constructor of
the backend. I am not sure to understand why you don't want this to
happen there, but I am sure that I don't want to spread the code that
concerns one backend to two distincts places (e.g. a class + a
function), this will get too complicated.

What about adding a class method in that case, that would answer to
the question, and not produce an instance of the backend ?

Last, about the proxy stuff, if you really want that, let's have in a
util module, but it should not interfer or change the existing logic.
It has to be a specific behaviour on the top of the "raise if
something is wrong" behaviour

Marcin Kasperski

unread,
Nov 15, 2010, 7:31:35 AM11/15/10
to python-...@googlegroups.com
> 1/ a user install the keyring and wants it to work. the keyring select
> one specific backend, and always the same, even if several backends
> are supported on the platform. ISTM that what we have fulfils this.

Not necessarily. The problem is that

- seemingly unrelated installations/deinstallations happen to change
keyring choice (for example on my Ubuntu laptop keyring for some time
used to pick KDE wallet, then after some update switched to gnome
keyring)

- in case a few keyrings are suitable the choice is not always perfect
(again, Linux case, if I run KDE but have GNOME_DESKTOP_SESSION_ID
set, I get gnome keyring in spite KDE wallet should be preferred)

I think it would be better if instead of prioritizing via plain list
in fixed order (_all_keyring constant in get_all_keyring) the library
was able to differentiate priorities according to the current context
(again, main use case is to be able to prefer Wallet under KDE and
Keyring under Gnome even if both are supported)

Another thing to consider is that maybe once we picked some backend
and saved some passwords, we could save this info somewhere to reuse
the same backend in the future. Or check all supported backends while
searching for the password...

Tarek Ziadé

unread,
Nov 15, 2010, 7:46:09 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 1:31 PM, Marcin Kasperski
<Marcin.K...@mekk.waw.pl> wrote:
>> 1/ a user install the keyring and wants it to work. the keyring select
>> one specific backend, and always the same, even if several backends
>> are supported on the platform. ISTM that what we have fulfils this.
>
> Not necessarily. The problem is that
>
> - seemingly unrelated installations/deinstallations happen to change
> keyring choice (for example on my Ubuntu laptop keyring for some time
> used to pick KDE wallet, then after some update switched to gnome
> keyring)

This (true) problem is orthogonal: even if we have configured a
specific backend, if it's removed, we are screwed as we lost stuff.
I don't know how we can prevent this. We could at least write
somewhere what is the backend in use, and give ways to warn the user
if it's gone.

> - in case a few keyrings are suitable the choice is not always perfect
> (again, Linux case, if I run KDE but have GNOME_DESKTOP_SESSION_ID
> set, I get gnome keyring in spite KDE wallet should be preferred

True. But the choice is also arbitrary. For example, even I use Gnome,
i could decide to use a file-base backend so I can share it into other
OSes.

I don't see how we can manage to make the 'perfect' choice since
backends ignore each other. They're just able to tell of they can work
on a specific context.

The only entity that knows more is the power user who can configure it.

>
> I think it would be better if instead of prioritizing via plain list
> in fixed order (_all_keyring constant in get_all_keyring) the library
> was able to differentiate priorities according to the current context
> (again, main use case is to be able to prefer Wallet under KDE and
> Keyring under Gnome even if both are supported)

Are we able to built a default list by context ? it sounds arbitrary
and hard to maintain. what happens for someone that create a new
backend ? Maybe we need one more priority level, and document that
backends need to raise it if they are on their preffered WM rather
than on a particular OS.

> Another thing to consider is that maybe once we picked some backend
> and saved some passwords, we could save this info somewhere to reuse
> the same backend in the future. Or check all supported backends while
> searching for the password...

Yeah, I had the same conclusion at the beginning of my answer :)

Alan Franzoni

unread,
Nov 15, 2010, 7:57:43 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 12:39 PM, Marcin Kasperski
<Marcin.K...@mekk.waw.pl> wrote:
>> Maybe it's better to force the user to configure it the first time and
>> then forget about it, and just fulfill the python karma "In the face
>> of ambiguity, refuse the temptation to guess." ?
>
> I don't find this idea to be too cute. After all firefox, evolution,
> etc etc don't ask where to save the passwords. This is techie detail.

Firefox, evolution and so on are full-blown appps that usually have
got os-specific builds. They can just pick the best keyring because
it's obvious.

Can you think of a system-unaware app (e.g. something that's written
entirely in python and can work out of the box without system-specific
builds or hooks or ifs) that can access a keyring in a transparent
way?

Moreover, keyring is a *library*, not an app in the common sense. If
the developer creates multiple os-aware apps and it's allowed to
inject a strategy to pick keyrings, he would probably be happier.

> All realistic scenarios I can think about could be solved by bare
> extension from "supported/unsupported" to "supported and
> native/supported/unsupported". Although some notion of "priority"
> could probably be easier to maintain in the long term.

Supported/unsupported is strictly related to the backend, it should be
dealt it in the constructor or in a factory method.

The ordering should be configurable, e.g. I think there should be a
KeyringPickStrategy or something like that to choose which keyring is
picked. A default strategy can be provided but the user should always
be given a chance to pick a different one.

Alan Franzoni

unread,
Nov 15, 2010, 8:14:07 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 12:46 PM, Tarek Ziadé <ziade...@gmail.com> wrote:
> I think there are two user stories:
>
> 1/ a user install the keyring and wants it to work. the keyring select
> one specific backend, and always the same, even if several backends
> are supported on the platform. ISTM that what we have fulfils this.

I just wonder what's the value of this story. How many "normal users"
want to use the keyring library?

Either it's a dep of an app that uses it, and then the app must be
given the chance to configure it, so that an app can configure the
Windows keyring in a Windows build, an OSX keyring in the Mac build,
and linux packagers can configure the right keyring dep depending on
the desktop environment, or it's pretty a power user/developer thing.

Also, if I've used the gnome keyring, I'd probably like to stick with
it; if tomorrow it doesn't work anymore, maybe because I've
uninstalled the python-gnomekeyring package, I'd like to have that
issue fixed, not to use the EncryptedFileKeyring instead.

> The current logic is to have this code locate in the constructor of
> the backend. I am not sure to understand why you don't want this to
> happen there, but I am sure that I don't want to spread the code that
> concerns one backend to two distincts places (e.g. a class + a
> function), this will get too complicated.

A classmethod or a static method will do just fine, the current logic
is in fact scattered between module code, functions, constructors, and
you must call supported() before you can understand whether you can
use such backend. If you want *all* the work to be done in the
constructor is fine BTW, I won't complain about that.

> Last, about the proxy stuff, if you really want that, let's have in a
> util module, but it should not interfer or change the existing logic.
> It has to be a specific behaviour on the top of the "raise if
> something is wrong" behaviour

I agree.


A quick resume of how would I like the keyring lib to be:


keyring.backend -> contains a certain number of classes and, ideally,
a KeyringBackendRegister or something like that, with all the registry
that can be supported. If I really want I can instantiate such backend

then we could have an entry point function in keyring like

def get_auto_backend(strategy=DefaultKeyringPickStrategy):
...


that just returns the "best" backend, but allows any client to change
the strategy if it wants to.

Let's stick to the users btw - who're they? I think they're all
developers using our library, they're not end users.

Tarek Ziadé

unread,
Nov 15, 2010, 8:35:41 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 2:14 PM, Alan Franzoni <mai...@franzoni.eu> wrote:
> On Mon, Nov 15, 2010 at 12:46 PM, Tarek Ziadé <ziade...@gmail.com> wrote:
>> I think there are two user stories:
>>
>> 1/ a user install the keyring and wants it to work. the keyring select
>> one specific backend, and always the same, even if several backends
>> are supported on the platform. ISTM that what we have fulfils this.
>
> I just wonder what's the value of this story. How many "normal users"
> want to use the keyring library?
> Either it's a dep of an app that uses it, and then the app must be
> given the chance to configure it, so that an app can configure the
> Windows keyring in a Windows build, an OSX keyring in the Mac build,
> and linux packagers can configure the right keyring dep depending on
> the desktop environment, or it's pretty a power user/developer thing.

How this is different ? The application can configure the keyring
configuration files to use a specific backend already, no ?

The issue is about choosing automatically the best backend, so the lib
v.s. app story does not help us here.
What I am saying here is that we already do this, for some values of
'best' backend.

If we want to improve that selection, we need to focus on how to
improve the way to select automatically a backend.

Maybe we need more levels than -1, 0 and 1. Maybe 2 could mean : "I am
the best backend for this environment",
so KDE is picked on KDE desktops etc..

>
> Also, if I've used the gnome keyring, I'd probably like to stick with
> it; if tomorrow it doesn't work anymore, maybe because I've
> uninstalled the python-gnomekeyring package, I'd like to have that
> issue fixed, not to use the EncryptedFileKeyring instead.
>
>> The current logic is to have this code locate in the constructor of
>> the backend. I am not sure to understand why you don't want this to
>> happen there, but I am sure that I don't want to spread the code that
>> concerns one backend to two distincts places (e.g. a class + a
>> function), this will get too complicated.
>
> A classmethod or a static method will do just fine, the current logic
> is in fact scattered between module code, functions, constructors, and
> you must call supported() before you can understand whether you can
> use such backend. If you want *all* the work to be done in the
> constructor is fine BTW, I won't complain about that.

Ok, so I am +1 for refactoring that in a classmethod.

>> Last, about the proxy stuff, if you really want that, let's have in a
>> util module, but it should not interfer or change the existing logic.
>> It has to be a specific behaviour on the top of the "raise if
>> something is wrong" behaviour
>
> I agree.
>
>
> A quick resume of how would I like the keyring lib to be:
>
>
> keyring.backend -> contains a certain number of classes and, ideally,
> a KeyringBackendRegister or something like that, with all the registry
> that can be supported. If I really want I can instantiate such backend
>
> then we could have an entry point function in keyring like
>
> def get_auto_backend(strategy=DefaultKeyringPickStrategy):
>    ...
>
>
> that just returns the "best" backend, but allows any client to change
> the strategy if it wants to.

I like the idea. What's DefaultKeyringPickStrategy ?

A callable that gets all backends and return one ?
A default behaviour would be to sort them by weights ?

> Let's stick to the users btw - who're they? I think they're all
> developers using our library, they're not end users.

That's what I had in mind.

We also need to make the difference between the problems we want
keyring to solve, and the ones that should be solved by the
applications. It's ok to have helpers for apps but we need to be
careful not to force some behaviours that would be app-specific

>
>
>
>
>
> --
> Alan Franzoni
> --
> contact me at public@[mysurname].eu
>

--
Tarek Ziadé | http://ziade.org

Alan Franzoni

unread,
Nov 15, 2010, 9:07:32 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 2:35 PM, Tarek Ziadé <ziade...@gmail.com> wrote:
> On Mon, Nov 15, 2010 at 2:14 PM, Alan Franzoni <mai...@franzoni.eu> wrote:
>> Either it's a dep of an app that uses it, and then the app must be
>> given the chance to configure it, so that an app can configure the
>> Windows keyring in a Windows build, an OSX keyring in the Mac build,
>> and linux packagers can configure the right keyring dep depending on
>> the desktop environment, or it's pretty a power user/developer thing.
>
> How this is different ? The application can configure the keyring
> configuration files to use a specific backend already, no ?

Globally? Once I install FooApp, it will change my keyringrc and
modify my preferences? And if there're two apps, they will fight and
keep changing my prefs?

> I like the idea. What's DefaultKeyringPickStrategy ?
>
> A callable that gets all backends and return one ?
> A default behaviour would be to sort them by weights ?

IMHO the KeyringPickStrategy interface would take all backends that
*work* (e.g. can be instanced) as input, and return a single backend
as output.

DefaultKeyringPickStrategy would work as follow:

- if a backend was configured in keyringrc and it's available, return it.
- if it was configured but it's unavailable, raise an exception.
- if nothing is configured in keyringrc, do some guessing and return
the best keyring, e.g. OSXKeychain for OSX, WinKeychain for Windows,
ecc.
- maybe once a keyring has been selected we should try saving that
information and show a warning if a keyring that was available is not
available anymore? I'm not sure about that.

Any client code is of course free of passing a different strategy
implementation.

> We also need to make the difference between the problems we want
> keyring to solve, and the ones that should be solved by the
> applications.  It's ok to have helpers for apps but we need to be
> careful not to force some behaviours that would be app-specific

I agree with you, I've already commented on my own ticket as well:

http://bitbucket.org/kang/python-keyring-lib/issue/32/error-on-keyring-password-get-set-shouldnt

My proposal wasn't a good one, there.

Tarek Ziadé

unread,
Nov 15, 2010, 9:27:35 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 3:07 PM, Alan Franzoni <mai...@franzoni.eu> wrote:
...

>
> Globally? Once I install FooApp, it will change my keyringrc and
> modify my preferences? And if there're two apps, they will fight and
> keep changing my prefs?

Not globally, at the app-level. FooApp can drive the choice by code
via set_keyring()
What prevents it to keep its own configuration to do this ?

>
>> I like the idea. What's DefaultKeyringPickStrategy ?
>>
>> A callable that gets all backends and return one ?
>> A default behaviour would be to sort them by weights ?
>
> IMHO the KeyringPickStrategy interface would take all backends that
> *work* (e.g. can be instanced) as input, and return a single backend
> as output.

Let's make it a simple callable. I don't think we need an interface
here for this.

>
> DefaultKeyringPickStrategy would work as follow:
>
> - if a backend was configured in keyringrc and it's available, return it.
> - if it was configured but it's unavailable, raise an exception.
> - if nothing is configured in keyringrc, do some guessing and return
> the best keyring, e.g. OSXKeychain for OSX, WinKeychain for Windows,
> ecc.

Sounds like what we already have in init_backend() . ("some guessing"
is made by sorting on .supported() )

so what about keeping it this way and just make the guessing part
configurable. A callable could be called to choose
between competing backends. (the default callable would sort on .supported())

so :

def default_strategy(backends):
return the highest .supported()

def init_backend(choose_backend=default_strategy):
...
backend = choose_backend(backends)
...

> - maybe once a keyring has been selected we should try saving that
> information and show a warning if a keyring that was available is not
> available anymore? I'm not sure about that.

I don't know either yet.

Marcin Kasperski

unread,
Nov 15, 2010, 9:30:08 AM11/15/10
to python-...@googlegroups.com
> Can you think of a system-unaware app (e.g. something that's written
> entirely in python and can work out of the box without system-specific
> builds or hooks or ifs) that can access a keyring in a transparent
> way?

Well, I try to write this way... So far I use keyring to store http
credentials in mercurial plugin
(http://pypi.python.org/pypi/mercurial_keyring) and to preserve
different credentials/token in scripts I use to access webservices
(for example http://pypi.python.org/pypi?:action=display&name=mekk.rtm
or http://pypi.python.org/pypi?:action=display&name=mekk.feeds). I
haven't written GUI app yet, but I don't think there would be much
difference.

The keyring value from appwriter point of view is that it resolves the
problem portably for me without requiring me to understand quirks and
cases of all the platforms. If I were to provide my own logic, I could
implement keyring selection myself as well. By using keyring I believe
the things will work even on platforms I've never seen.

Therefore I feel the good place to solve correct prioritization is
keyring itsellf, not apps which use it.

Alan Franzoni

unread,
Nov 15, 2010, 10:44:32 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 3:27 PM, Tarek Ziadé <ziade...@gmail.com> wrote:
> On Mon, Nov 15, 2010 at 3:07 PM, Alan Franzoni <mai...@franzoni.eu> wrote:
> ...
>>
>> Globally? Once I install FooApp, it will change my keyringrc and
>> modify my preferences? And if there're two apps, they will fight and
>> keep changing my prefs?
>
> Not globally, at the app-level. FooApp can drive the choice by code
> via set_keyring()
> What prevents it to keep its own configuration to do this ?

I think we ought to drop (after deprecating) the global, simil-static
set_keyring/get_keyring and get_password/set_password, since they rely
on a global, mutable (if it is set) keyring backend which has little
purpose, and they're cumbersome to be passed along. If I want a
dependency in my client code to use a keyring implementation, I should
inject it into it, not force it using a global get_keyring or
get_password func. Dependency injection!

If we use the get_auto_keyring() approach, we've got no global set/get
keyring, because it's got no purpose, and that function just returns a
backend. If somebody just instances a backend from keyring.backend,
he's got an object with the very same interface as the object returned
by get_auto_keyring().

Also, why would you want to set the keyring as global when you've
already got it?

> Let's make it a simple callable. I don't think we need an interface
> here for this.

it can be a callable, I wasn't going really deep in implementation details.

>> DefaultKeyringPickStrategy would work as follow:
>>
>> - if a backend was configured in keyringrc and it's available, return it.
>> - if it was configured but it's unavailable, raise an exception.
>> - if nothing is configured in keyringrc, do some guessing and return
>> the best keyring, e.g. OSXKeychain for OSX, WinKeychain for Windows,
>> ecc.
>
> Sounds like what we already have in init_backend()  . ("some guessing"
> is made by sorting on .supported() )
>
> so what about keeping it this way and just make the guessing part
> configurable. A callable could be called to choose
> between competing backends. (the default callable would sort on .supported())

I still think that's not a good approach. supported() simply smells.
It does not belong to the keyring interface and violates the SRP. I
don't like it.

Also, supported() has little global knowledge of the environment where
it's being called; while a strategy could decide on which backends are
available AND which keyring is configured AND which platform we're on,
a keyring's backend supported() just knows if it's available itself
and which platform we're on. It's much less information

Tarek Ziadé

unread,
Nov 15, 2010, 11:25:56 AM11/15/10
to python-...@googlegroups.com
My head is exploding :D -- we are going in many directions and talking
about massive refactorings. This thread is not focused anymore imo.

I suggest that we do two things:

1/ Alan, maybe you could write a global design document on a wiki,
describing how you want it to be, we can feedback on, for "Keyring v2"
2/ in the meantime, I suggest that we list small changes we can do
now, to enhance Keyring v1

--
Tarek Ziadé | http://ziade.org

Benji York

unread,
Nov 15, 2010, 11:40:38 AM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 11:25 AM, Tarek Ziadé <ziade...@gmail.com> wrote:
> I suggest that we do two things:
>
> 1/ Alan, maybe you could write a global design document on a wiki,
> describing how you want it to be, we can feedback on, for "Keyring v2"
> 2/ in the meantime, I suggest that we list small changes we can do
> now, to enhance Keyring v1

+1
--
Benji York

Alan Franzoni

unread,
Nov 15, 2010, 12:19:54 PM11/15/10
to python-...@googlegroups.com
On Mon, Nov 15, 2010 at 5:25 PM, Tarek Ziadé <ziade...@gmail.com> wrote:

[cut]

I didn't mean to do all the things within a single release, but I
think yours might be a good idea, I'll put down everything in a list
then we can review intents and prioritize tasks.

Reply all
Reply to author
Forward
0 new messages