Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

don't require file to be writeable if we're not going to write to it #281

Closed
wants to merge 2 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 10 additions & 6 deletions rtree/index.py
Original file line number Diff line number Diff line change
Expand Up @@ -230,12 +230,13 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
# check we can read the file
f = str(basename) + "." + self.properties.idx_extension
p = os.path.abspath(f)
d = os.path.dirname(p)
file_exists = os.path.exists(f)

# assume if the file exists, we're not going to overwrite it
# assume we're not going to overwrite an existing file
# unless the user explicitly set the property to do so
if os.path.exists(p):
self.properties.overwrite = bool(kwargs.get("overwrite", False))

self.properties.overwrite = bool(kwargs.get("overwrite", False))
if file_exists:
# assume we're fetching the first index_id. If the user
# set it, we'll fetch that one.
if not self.properties.overwrite:
Expand All @@ -244,8 +245,11 @@ def __init__(self, *args: Any, **kwargs: Any) -> None:
except RTreeError:
self.properties.index_id = 1

d = os.path.dirname(p)
if not os.access(d, os.W_OK):
writing_required = (not file_exists) or (
file_exists and self.properties.overwrite
)
writeable = os.access(f, os.W_OK) if file_exists else os.access(d, os.W_OK)
if writing_required and not writeable:
message = "Unable to open file '%s' for index storage" % f
raise OSError(message)
elif storage:
Expand Down
32 changes: 32 additions & 0 deletions tests/test_index.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
from __future__ import annotations

import ctypes
import os
import pathlib
import pickle
import stat
import tempfile
import unittest
from typing import Dict, Iterator, Tuple
Expand Down Expand Up @@ -607,6 +610,35 @@ def test_overwrite(self) -> None:
idx = index.Index(tname, overwrite=True)
assert isinstance(idx, index.Index)

def _make_read_only_index(self) -> str:
"""Create a read-only index & return the path without extension"""
dirname = pathlib.Path(tempfile.mkdtemp())
file_path_no_extension = dirname / "index"
idx_filename = file_path_no_extension.with_suffix(".idx")

idx = index.Index(str(file_path_no_extension))
idx.add(1, (2, 2))
del idx

# Now that the index is written, make it read-only
os.chmod(idx_filename, stat.S_IREAD)
assert not os.access(idx_filename, os.W_OK)

return str(file_path_no_extension)

def test_overwrite_uneditable_throws(self) -> None:
"""Existing index with overwrite should throw if we can't edit the file"""
file_path_no_extension = self._make_read_only_index()

with pytest.raises(OSError):
index.Index(file_path_no_extension, overwrite=True)

def test_read_only_ok_if_overwrite_false(self) -> None:
file_path_no_extension = self._make_read_only_index()

idx = index.Index(file_path_no_extension, overwrite=False)
assert isinstance(idx, index.Index)


class IndexNearest(IndexTestCase):
def test_nearest_basic(self) -> None:
Expand Down