COVID-IWG / epimargin

networked, stochastic SIRD epidemiological model with Bayesian parameter estimation and policy scenario comparison tools
https://www.adaptivecontrol.org/
MIT License
9 stars 5 forks source link

Write issue in directory returned by `cwd()` #116

Closed dilawar closed 3 years ago

dilawar commented 3 years ago

https://github.com/openjournals/joss-reviews/issues/3464

Permission issues at the very first run.

After pip3 install epimargin on a Linux box. I ran the following snippets in python console.

from itertools import cycle

import epimargin.plots as plt
import numpy as np
import pandas as pd
from epimargin.utils import setup

(data, figs) = setup() # creates convenient directories
plt.set_theme("minimal")

I hit by permission issues when application tried to create default directory. Is is necessary to use /usr/bin/ to save data. In line 44 below, may be root can be set to someplace in user's $HOME?

<ipython-input-1-710a13386d8f> in <module>
      6 from epimargin.utils import setup
      7 
----> 8 (data, figs) = setup() # creates convenient directories
      9 plt.set_theme("minimal")

~/Work/FORKES/epimargin/epimargin/utils.py in setup(**kwargs)
     42     logging.basicConfig(**kwargs)
     43     logging.getLogger('flat_table').addFilter(lambda _: 0)
---> 44     return (mkdir(root / "data"), mkdir(root / "figs"))
     45 
     46 def fillna(array):

~/Work/FORKES/epimargin/epimargin/utils.py in mkdir(p, exist_ok)
     30 
     31 def mkdir(p: Path, exist_ok: bool = True) -> Path:
---> 32     p.mkdir(exist_ok = exist_ok)
     33     return p
     34 

/usr/lib/python3.9/pathlib.py in mkdir(self, mode, parents, exist_ok)
   1311         """
   1312         try:
-> 1313             self._accessor.mkdir(self, mode)
   1314         except FileNotFoundError:
   1315             if not parents or self.parent == self:

PermissionError: [Errno 13] Permission denied: '/usr/bin/data'

On Linux and OSX, https://github.com/COVID-IWG/epimargin /blob/1a8094ae8173a9f09f2efc5b872ac56d67a86c6f/epimargin/utils.py#L18 most likely to return /usr/bin since argv0 is /usr/bin/python3.

Another solution is to check if the cwd() is writable by the user. If not, default to a user-writable directory in user's $HOME? If not, the application needs to be run as root or sudo user which is not advisable.

satejsoman commented 3 years ago

Hi @dilawar - thanks for flagging this. I've just merged #118, which uses the __file__ builtin (when available) to construct a directory in the same location as the script. When that builtin is not available, we default to what pathlib.Path.cwd() provides.

We don't expect /usr/bin to be the default location for data; our intention was to create directories in the same folder as the client script. We do expect that client code calling this library will be run from a user-writable location, which I think is reasonable.

My testing indicates that argv[0] picks up the script location rather than the binary location. As an example, consider this following test script (test.py), located in my home directory:

from sys import argv
from pathlib import Path

print(argv[0])
print(Path(argv[0]).resolve().parent)
try:
    print(Path(__file__).resolve().parent)
except NameError:
    print("__file__ variable not available")
print(Path.cwd())

When I run /usr/bin/python3 test.py, I get:

test.py
/Users/satej
/Users/satej
/Users/satej

Does that make sense? Let me know if I've misunderstood something or have assumed something too specific about users' set ups.