Skip to content

What to do when ~/.astropy is not writeable - #123

Merged
eteq merged 11 commits into
astropy:masterfrom
eteq:astropy-dir-fallback
Jan 26, 2012
Merged

eteq merged 11 commits into
astropy:masterfrom
eteq:astropy-dir-fallback

Conversation

@eteq

@eteq eteq commented Jan 19, 2012

Copy link
Copy Markdown
Member

While trying to run the astropy build on a mac with Jenkins to automate testing with different Python versions, I ran into an issue. The tests are run using the anonymous user, and when Jenkins tries to build astropy, it needs to be able to create the .astropy directory in the home directory. However, in this case, it tries to access /var/root, which is of course not writeable:

Started by user anonymous
Checkout:workspace / /Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace - hudson.remoting.LocalChannel@611c4041
Using strategy: Default
Last Built Revision: Revision 48af8d6b12f8b2964e037ee7137ad91fa298d5b7 (origin/HEAD, origin/master)
Checkout:workspace / /Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace - hudson.remoting.LocalChannel@611c4041
Fetching changes from 1 remote Git repository
Fetching upstream changes from git://github.com/astropy/astropy.git
Seen branch in repository origin/HEAD
Seen branch in repository origin/master
Commencing build of Revision 48af8d6b12f8b2964e037ee7137ad91fa298d5b7 (origin/HEAD, origin/master)
Checking out Revision 48af8d6b12f8b2964e037ee7137ad91fa298d5b7 (origin/HEAD, origin/master)
Warning : There are multiple branch changesets here
[workspace] $ /bin/sh -xe /var/folders/zz/zzzivhrRnAmviuee+++++E++++2/-Tmp-/hudson8835089690851720710.sh
+ /opt/local/bin/python2.7 setup.py build
Traceback (most recent call last):
  File "setup.py", line 11, in <module>
    import astropy
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/__init__.py", line 22, in <module>
    from .tests.helper import TestRunner
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/tests/__init__.py", line 8, in <module>
    from . import helper
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/tests/helper.py", line 16, in <module>
    from ..config import ConfigurationItem
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/__init__.py", line 11, in <module>
    from .data import *
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/data.py", line 15, in <module>
    'dataurl','http://data.astropy.org/','URL for astropy remote data site.')
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/configs.py", line 135, in __init__
    self()
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/configs.py", line 264, in __call__
    sec = get_config(self.module)
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/configs.py", line 342, in get_config
    cfgfn = join(get_config_dir(),rootname+'.cfg')
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/paths.py", line 109, in get_config_dir
    return path.abspath(_find_or_create_astropy_dir('config',linkto))
  File "/Users/Shared/Jenkins/Home/jobs/astropy-python2.7/workspace/astropy/config/paths.py", line 154, in _find_or_create_astropy_dir
    mkdir(innerdir)
OSError: [Errno 13] Permission denied: '/var/root/.astropy'
Build step 'Execute shell' marked build as failure
Finished: FAILURE

Of course, I can fix this by doing:

HOME=/Users/Shared/Jenkins python setup.py build

but this got me thinking that maybe at least (but not necessarily all) of the following should probably happen:

  • ~/.astropy should be created on install, not build (in my view, build should only affect the local directory, while install can place files outside the tree)
  • there should be a way to disable creating ~/.astropy on build for this kind of situation
  • if ~/.astropy cannot be created, a warning should be raised, but this should not be fatal

@eteq, @mdboom, and @iguananaut - since you've been involved in the ~/.astropy stuff I was wondering whether you have any thoughts regarding how this should behave?

@mdboom

mdboom commented Jan 7, 2012

Copy link
Copy Markdown
Contributor

~/.astropy needs to be created upon first import... it should not be part of setup.py at all. Think of the use case of installing in a central location on a multi-user machine. It should resolve this situation, too, unless i'm missing something.

@eteq

eteq commented Jan 8, 2012

Copy link
Copy Markdown
Member

The trouble is deciding when "first import" is - after all, there's an import astropy in setup.py. The way it works now is that it is created at first import, if it isn't found already... its just that that first import is somewhere in the setup script (I'm not sure actually why it's doing it in build, but it doesn't necessarily surprise me).

My idea was that for multi-user machines, it will just always look for whatever the correct home is for the current user who's actually running that python process... as it stands right now, any .astropy directory created by the root user at install will not be used when some other user imports astropy - it will just create a new /home/whateveruser/.astropy directory.

So this could be changed to check for if it's in setup, and if so, not do any of the creating. I think that will break some of the tests, though... Alternatively, we could just have it fail gracefully if it can't access the .astropy directory, and just assume all defaults for the configuration and only fail if someone tries to use the cache stuff (which of course requires a writeable directory).

@astrofrog

Copy link
Copy Markdown
Member Author

I think that whatever we do, if ~/.astropy is not writeable, astropy should still import, but with a warning. I don't think an exception should be raised (astropy can still function with the default config).

@eteq

eteq commented Jan 9, 2012

Copy link
Copy Markdown
Member

Yep, that definitely makes sense for config files... But what about accessing the cache? One thing that could be done might be to use the NamedTemporaryFile mechanism as a fallback if the cache can't be written to (remember that we sometimes need a file name), but to make that work we wouldn't be able to delete the temporary files through astropy (the user would have to know to clear their temp dir). Or we could just have it throw an exception whenever someone asks for an actual filename...

@mdboom

mdboom commented Jan 9, 2012

Copy link
Copy Markdown
Contributor

@eteq: Maybe we could have an atexit handler that removes the temporary cache directory if one was created.

@mdboom

mdboom commented Jan 9, 2012

Copy link
Copy Markdown
Contributor

@eteq: I think what you propose 3 comments up here seems reasonable.

@embray

embray commented Jan 18, 2012

Copy link
Copy Markdown
Member

Why are the tests relying on ~/.astropy in the first place?

I would say that import astropy from setup.py shouldn't rely on ~/.astropy at all--I thought we had a global variable for "in setup.py". The tests should use some temp dir in place of ~/.astropy, right? I've been a little out of the loop the last few weeks though, so I'm not sure if there's a problem with that...

@eteq

eteq commented Jan 19, 2012

Copy link
Copy Markdown
Member

The tests rely on ~/.astropy because that's how the real system works - and if the tests are supposed to make sure the correct astropy directory can be found, they need to actually go through all the motions. Remember that locating the "home" directory can be surprisingly non-trivial on some platforms... I suppose the test could be made to only use a temporary directory, but to me it seems like that's not actually testing the right functionality. And anyway, this is independent of that because one could imagine a scenario where the home directory is for some reason inacessible in normal use instead of just when the tests are being run (say the ~/.astropy directory is a symlink to a network drive or something).

@astrofrog

Copy link
Copy Markdown
Member Author

I still think that in any case, related to the original ticket, astropy should never fail to import if ~/.astropy is not accessible, whether in setup.py or afterwards. I don't want the import to fail if as you said, the home directory is temporarily unavailable for e.g. network reasons.

@eteq

eteq commented Jan 19, 2012

Copy link
Copy Markdown
Member

Agreed - and the code I just attached does exactly that - if ~/.astropy is unavailable, ConfigurationItems will just use their default (unless set in user code), and remote data downloads will go to a temporary file. In both cases, warnings are given that the astropy directory is inacessible. In the latter case, the temporary file is also included in the warning so the user can go and delete it later on if they so desire.

@astrofrog

Copy link
Copy Markdown
Member Author

I guess what I'm trying to say is that if ~/.astropy cannot be written/read, it is not crucial to astropy and should not raise an exception. In that case, the default config would be used, and no caching would take place.

@astrofrog

Copy link
Copy Markdown
Member Author

@eteq - ok, that sounds sensible. I sent my last comment before seeing yours.

@eteq

eteq commented Jan 19, 2012

Copy link
Copy Markdown
Member

Ok, sounds good - I'll give it a few days for review, and assuming there aren't any big problems I'll merge and close the issue.

@embray

embray commented Jan 19, 2012

Copy link
Copy Markdown
Member

When the tests do use ~/.astropy they don't disturb anything in there though, do they? Wouldn't want that once people are actually using this and have files and configurations in there that shouldn't be disturbed.

@mdboom

mdboom commented Jan 19, 2012

Copy link
Copy Markdown
Contributor

I understand the argument that it is hard to test the configuration system itself without actually accessing the configuration files. However, I think, as @iguananaut suggested, we shouldn't touch those files during setup. I wouldn't expect setup.py build to create anything outside of the build directory, and Linux packaging systems, for example, generally enforce this policy.

There is the other issue that we don't want user's settings to impact the tests themselves. We had this issue in matplotlib. Imagine a setting that turns warnings into errors for example (one such setting already exists in astropy.io.vo). What matplotlib does there is use all default settings during test runs, and write tests that explicitly change some config values in order to test the effect of those config values. It should be possible to set a flag in conftest.py that would prevent the loading of configuration from files.

As for testing configuration itself, it should be possible to set $HOME to somewhere under tmp, check that it creates files there correctly etc. without touching the real home directory and without having settings that impact other tests in the test suite.

Comment thread astropy/config/data.py

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We could add a sys.atexit handler here so the file is automatically cleared when the interpreter is done.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the commit I added, I've added this, controlled by a configuration item (defaulting to delete) - I imagine there are some cases where a user might want to keep the file after it's downloaded. It's maybe a bit silly given that the configuration file itself is probably inacessible in these cases, but ConfigurationItem.set will still work if someone really wants it.

@embray

embray commented Jan 19, 2012

Copy link
Copy Markdown
Member

I agree with @mdboom's suggestion of setting $HOME to a tmp directory for the tests. There could (and should) still be a test or tests for the function that finds the user's $HOME (the result of such a test would depend entirely on which platform it's run on, but that's fine too).

@eteq

eteq commented Jan 20, 2012

Copy link
Copy Markdown
Member

@iguananaut and @mdboom - I see your point here - and pytest makes this pretty easy, actually, with the monkeypatch funcarg - if you look at the tests I added in this pull request, both new functions have a signature that includes monkeypatch, and then at the beginning I do monkeypatch.setenv('XDG_CONFIG_HOME', 'foo'). That sets the environment variable for that test, and then reverts it to what it should be for remaining tests. Should we do that, or instead just set use the test command or a py.test plugin to set $HOME before any of the tests run?

Also, perhaps one of you should create this as a separate issue/pull request (or I can - I just want to make sure you aren't attached to it being in this particular PR)? I think we want this pull request regardless, and while related, I think having an inaccessible .astropy fall back to defaults and having the tests run separately are slightly different issues.

@eteq

eteq commented Jan 23, 2012

Copy link
Copy Markdown
Member

@astrofrog - can you confirm that with the changes in this PR, the original issue is actually fixed?

@astrofrog

Copy link
Copy Markdown
Member Author

@eteq

eteq commented Jan 23, 2012

Copy link
Copy Markdown
Member

The second one is happening because if it can't access the astropy directory, it leaves the ConfigObj filename as None (the default). So it's also expected behavior if the configuration directory is inaccessible.

So what do you think is the best way to deal with this? I could just add extra clauses to ignore OSErrors that include "permission denied" for the first one, and the second I could just check for None and have it do nothing if its None. But that could potentially mask future bugs, I suppose. Or I could just merge this as-is, as the suggestions of @mdboom and @iguananaut would make this problem irrelevant for you once we implemented that (a temporary directory for the config files, that is).

@astrofrog

Copy link
Copy Markdown
Member Author

Ok, I agree that the second failed test is not a big issue, so as far as I'm concerned, this is fine to merge for now.

eteq added a commit that referenced this pull request Jan 26, 2012
config and data fallback to defaults when $HOME/.astropy is not writeable
@eteq
eteq merged commit 3fde849 into astropy:master Jan 26, 2012
keflavich pushed a commit to keflavich/astropy that referenced this pull request Oct 9, 2013
config and data fallback to defaults when $HOME/.astropy is not writeable
embray added a commit to embray/astropy that referenced this pull request Jan 23, 2015
…3_inv

Adding builtins.object to local python3 inventory to fix broken links ...
embray added a commit to embray/astropy that referenced this pull request Jan 23, 2015
@eteq
eteq deleted the astropy-dir-fallback branch May 3, 2015 17:16
astrofrog referenced this pull request in astrofrog/astropy Nov 23, 2016
jeffjennings pushed a commit to jeffjennings/astropy that referenced this pull request Jul 2, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants