Skip to content

Commit

Permalink
check_path returns a real path if symlink passed
Browse files Browse the repository at this point in the history
  • Loading branch information
davidvicenteranz committed Sep 22, 2020
1 parent 16c02d3 commit 75fe5c8
Show file tree
Hide file tree
Showing 6 changed files with 73 additions and 18 deletions.
1 change: 1 addition & 0 deletions not_real_path
3 changes: 3 additions & 0 deletions snapshotstore/exceptions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,4 +7,7 @@ class PathIsNotDir(Exception):
pass

class PathIsNotWritable(Exception):
"""Raises when path is not writeable."""

class PathIsNotReadable(Exception):
"""Raises when path is not writeable."""
8 changes: 7 additions & 1 deletion snapshotstore/models/__init__.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import os
from pathlib import Path

from snapshotstore.exceptions import PathNotExistsError, PathIsNotDir, PathIsNotWritable
from snapshotstore.exceptions import PathNotExistsError, PathIsNotDir, PathIsNotWritable, PathIsNotReadable

"""
datastore
Expand Down Expand Up @@ -32,16 +32,22 @@ class PathClassModel:
def check_path(path: str, raise_on_not_exists=True):
"""Check if path is usable. Must exists, be a directory and writeble by this instance."""
path = Path(path)
if path.is_symlink():
path = Path(os.readlink(path))

if not path.exists() and raise_on_not_exists:
raise PathNotExistsError(f'Path {path} does not exist.')
if not path.is_dir():
raise PathIsNotDir(f'Path {path} is not a directory.')
if not os.access(path, os.R_OK):
raise PathIsNotReadable(f'Path {path} exists, but is not readable.')
if raise_on_not_exists and not os.access(path, os.W_OK):
raise PathIsNotWritable(f'Path {path} exists, but is not writable.')

if path.is_absolute():
return path


return path.absolute()

class VersionBase(PathClassModel):
Expand Down
16 changes: 16 additions & 0 deletions tests/config.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import os
import sys
from pathlib import Path
import tempfile

TMP_PATH = tempfile.gettempdir()
test_path = Path(os.getcwd()).joinpath('test_volume')
relative_path = './test_volume'

if not test_path.exists():
test_path = Path(os.getcwd()).joinpath('tests').joinpath('test_volume')

if not Path(relative_path).exists():
relative_path = './tests/test_volume'

print('test_path', test_path, file=sys.stderr)
51 changes: 34 additions & 17 deletions tests/test_pathClassModel.py
Original file line number Diff line number Diff line change
@@ -1,23 +1,9 @@
import sys
from pathlib import Path
from unittest import TestCase

from snapshotstore.exceptions import PathNotExistsError, PathIsNotDir, PathIsNotWritable
from snapshotstore.models import PathClassModel
import os

TMP_PATH = '/tmp'
test_path = Path(os.getcwd()).joinpath('test_volume')
relative_path = './test_volume'

if not test_path.exists():
test_path = Path(os.getcwd()).joinpath('tests').joinpath('test_volume')

if not Path(relative_path).exists():
relative_path = './tests/test_volume'

print('test_path', test_path, file=sys.stderr)

from snapshotstore.exceptions import PathNotExistsError, PathIsNotDir, PathIsNotWritable, PathIsNotReadable
from snapshotstore.models import PathClassModel
from .config import TMP_PATH, test_path, relative_path

files = result = [os.path.join(dp, f) for dp, dn, filenames in os.walk(test_path) for f in filenames]

Expand All @@ -40,6 +26,7 @@ def test_file_as_path(self):
def test_not_writable_dir(self):
from stat import S_IREAD
not_writable_path = str(Path(relative_path).joinpath('not_writable_dir').absolute())
# Create only readable dir to test
os.mkdir(not_writable_path, S_IREAD)
self.assertFalse(Path(relative_path).is_absolute())
self.assertTrue(PathClassModel.check_path(relative_path).is_absolute())
Expand All @@ -48,8 +35,38 @@ def test_not_writable_dir(self):
os.chmod(not_writable_path, mode=7777)
os.removedirs(not_writable_path)

def test_not_readble_dir(self):
from stat import S_IWRITE
not_writable_path = str(Path(relative_path).joinpath('not_readable_dir').absolute())
# Create only writable dir to test
os.mkdir(not_writable_path, S_IWRITE)
self.assertFalse(Path(relative_path).is_absolute())
self.assertTrue(PathClassModel.check_path(relative_path).is_absolute())
with self.assertRaises(PathIsNotReadable) as context:
PathClassModel.check_path(not_writable_path)
os.chmod(not_writable_path, mode=7777)
os.removedirs(not_writable_path)

def test_relative_path(self):
""""Test chek_path returns absolute path"""
self.assertEqual(str(PathClassModel.check_path('.')), os.getcwd())
self.assertTrue(isinstance(PathClassModel.check_path('.'), Path))


def test__soft_link(self):
"""Ensures path is not symlink and is an abcolute path"""
from stat import S_IWRITE, S_IREAD
real_path = str(Path(test_path).joinpath('real_path').absolute())
not_real_path = str(Path(test_path).joinpath('not_real_path').absolute())

os.mkdir(real_path, S_IWRITE | S_IREAD)
self.assertFalse(Path(real_path).is_symlink())
os.symlink(real_path, not_real_path, target_is_directory=True)
self.assertTrue(Path(not_real_path).is_symlink())

# Ensures path is the real path
self.assertEqual(PathClassModel.check_path(not_real_path).absolute(), Path(real_path).absolute())

os.remove(not_real_path)
self.assertFalse(Path(not_real_path).exists())
os.removedirs(real_path)
12 changes: 12 additions & 0 deletions tests/test_storeBase.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
from pathlib import Path
from unittest import TestCase
from snapshotstore.models import StoreBase

from .config import TMP_PATH, test_path, relative_path

class TestStoreBase(TestCase):
def test__init__(self):
self.assertTrue(isinstance(StoreBase('.').path, Path))
self.assertEqual(StoreBase('.').path, Path('.').absolute())
self.assertTrue(StoreBase('.').path.exists())
Path('.').is_block_device()

0 comments on commit 75fe5c8

Please sign in to comment.