7

A bizarre import error is preventing me from installing a mercurial extension.

I'm trying to get the mercurial_keyring extension running so that I don't have to type in my user name and password every time I use mercurial for a project.

I'm using Python 2.7.1. I installed mercurial with the binary provided at https://www.mercurial-scm.org/.

I installed keyring and mercurial_keyring with pip.

I first tried to add the extension by adding this to ~/.hgrc:

[extensions]
...
mercurial_keyring = 

as indicated in the installation instructions here. However, I got the following error:

*** failed to import extension mercurial_keyring: No module named mercurial_keyring

From the same installation instructions, I tried pointing mercurial directly to the mercurial_keyring.py file, which worked.

[extensions]
...
hgext.mercurial_keyring = /Library/Frameworks/Python.framework/Versions/2.7/lib/python2.7/site-packages/mercurial_keyring.py

And things seemed to be moving along.

However, when I try to execute any mercurial commands requiring my password so that it will be saved by keyring (e.g. hg pull, hg push) I get the error

abort: No module named keyring!

The most confusing part is that there is a clear

import keyring

in line 28 of mercurial_keyring.py that is resolved without any problems. In fact, any import keyring succeeds outside classes and methods and fails inside them!

Just for the sake of thoroughness, I'll mention that this error arises in the mercurial_keyring.py in the PasswordStore class in the get_http_password method when the following is attempted

return keyring.get_password(...)

Any thoughts?

I have the feeling that I'm missing something obvious, but I've spent a good deal of time trying to figure this out and google has not been particularly helpful so far. Any input will be greatly appreciated.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
arturomp
  • 28,790
  • 10
  • 43
  • 72
  • What output do you get when running `python -m site`? (you'll need to add it to the question, it won't be readable as a comment) – ncoghlan Mar 03 '11 at 01:11
  • My current suspicion is that you have a problem with either your 2.7 install or the system 2.6 install, such that mercurial is using one of them, while your manual tests are using the other. – ncoghlan Mar 03 '11 at 01:20

7 Answers7

9

Most likely, hg is running using the system python (2.6) rather than the copy of 2.7 you have installed.

Try installing mercurial_keyring and keyring under 2.6, and see if that gets things working as expected.

ncoghlan
  • 40,168
  • 10
  • 71
  • 80
  • Yes! I had tried that but it didn't work. I've updated my question to expand on that point. – arturomp Mar 03 '11 at 21:21
  • Thanks for the clarification. Given the `ImportError` you get when using the standard configuration instructions for `mercurial_keyring`, I'm inclined to go back to my first guess (i.e. `hg` is using the system installation of 2.6, rather than the copy of 2.7 where you installed the extra modules). I have updated my answer accordingly. – ncoghlan Mar 04 '11 at 01:51
  • Thanks! You're right. I think the problem is that the binary form the mercurial website installs to the system's Python 2.6, instead of the default one, which was 2.7 in my case. Instead of reverting to 2.6 I've now installed mercurial for python 2.7 with pip. Then I just renamed `/usr/local/bin/hg` to `/usr/local/bin/hg-2.6` and symlinked `/usr/local/bin/hg` to `/Library/Frameworks/Python.framework/Versions/2.7/bin/hg`. – arturomp Mar 04 '11 at 21:47
  • 5
    `Try installing mercurial_keyring and keyring under 2.6, and see if that gets things working as expected.` ... how do you do this? – Jeremy S. Jul 31 '14 at 16:21
1

I encountered the same issue and resolved it by installing extension with easy install: sudo easy_install mercurial_keyring

This installs it under the same python that mercurial uses.

Priit
  • 470
  • 7
  • 21
1

@ncoghlan's answer is right (for me, anyway), but incomplete and I don't have enough rep points to comment. (Jeremy S, I think this answers your question.)

To install for a specific version of Python, use the following modifications: Instead of

easy_install keyring

Use

easy_install-2.6 keyring

Same applies for any of the easy_install or other Python commands. I found this from an example for pip here: How to install a module use pip for specific version of?

Community
  • 1
  • 1
Mike
  • 69
  • 6
1

Mercurial uses a feature called 'demandimport' which postpones the import of modules, until the first time they are used. So, your

import keyring

won't fail at that line, but it will wail only when it's used first(i.e)

return keyring.get_password(...)

tamizhgeek
  • 1,371
  • 3
  • 13
  • 25
  • Good to know! Thanks! A quick google search failed to give me a definitive answer or documentation on this. Do you have any reliable sources you could share? – arturomp Mar 04 '11 at 19:04
  • search in the mercurial-devel arhcives and mercurial wiki. Well I don't know the reason for your actual problem, but just pointing out the reason why import keyring is not failing. – tamizhgeek Mar 04 '11 at 21:19
1

I ran into same issue. The issue was I installed mercurial via brew and installed the keyring using pip. Uninstalling the mercurial in brew and then installing mercurial via pip solved the issue for me.

pip install mercurial
godwyn
  • 11
  • 1
0

My issue was that I installed Mercurial via macports, but the extension via pip. To solve it, I had to install the extension via macports as well.

sudo port install py-keyring py-mercurial_keyring
reubano
  • 5,087
  • 1
  • 42
  • 41
0

imports in methods are evaluated when they're called, whereas top-level imports are evaluated immediately. The behavior of imports can be modified, have a look at the imp and site modules as well as sys.path. What is probably happening is that some code at the end of the file (figuratively, may also be a function call on initialization or so) modifies the import behavior by accident or to prevent and notice inadvertent late imports.

phihag
  • 278,196
  • 72
  • 453
  • 469