Skip to content
Open
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
26 changes: 19 additions & 7 deletions snakemake_interface_storage_plugins/storage_provider.py
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ def __init__(
is_default=False,
):
self.logger: Logger = logger
self.wait_for_free_local_storage: int = wait_for_free_local_storage
self.wait_for_free_local_storage: Optional[int] = wait_for_free_local_storage
try:
local_prefix.mkdir(parents=True, exist_ok=True)
except OSError as e:
Expand All @@ -90,10 +90,19 @@ def rate_limiter(self, query: str, operation: Operation):
else:
key = self.rate_limiter_key(query, operation)
if key not in self._rate_limiters:
max_status_checks_frac = Fraction(
self.settings.max_requests_per_second
or self.default_max_requests_per_second()
).limit_denominator()
rate = self.default_max_requests_per_second()
if (
self.settings is not None
and self.settings.max_requests_per_second is not None
):
rate = self.settings.max_requests_per_second

if rate is None or rate <= 0:
raise WorkflowError(
"max_requests_per_second must be a positive number, "
f"got {rate}"
)
max_status_checks_frac = Fraction(rate).limit_denominator()
self._rate_limiters[key] = Throttler(
rate_limit=max_status_checks_frac.numerator,
period=max_status_checks_frac.denominator,
Expand Down Expand Up @@ -159,10 +168,13 @@ def safe_print(self, query: str) -> str:
@property
def is_read_write(self) -> bool:
from snakemake_interface_storage_plugins.storage_object import (
StorageObjectReadWrite,
StorageObjectRead,
StorageObjectWrite,
)

return isinstance(self.storage_object_cls, StorageObjectReadWrite)
return isinstance(
self.get_storage_object_cls(), StorageObjectRead
) and isinstance(self.get_storage_object_cls(), StorageObjectWrite)

Comment on lines +171 to 178
Copy link
Contributor

Choose a reason for hiding this comment

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

⚠️ Potential issue

is_read_write uses isinstance() on a class – should be issubclass()

self.get_storage_object_cls() returns a class, but isinstance() expects an instance.
As written, the expression will always evaluate to False, so is_read_write will never report True, even when the storage object supports both read and write.

-        return isinstance(
-            self.get_storage_object_cls(), StorageObjectRead
-        ) and isinstance(self.get_storage_object_cls(), StorageObjectWrite)
+        cls = self.get_storage_object_cls()
+        return issubclass(cls, StorageObjectRead) and issubclass(cls, StorageObjectWrite)

This also avoids the double call to get_storage_object_cls().
Failing to fix this will silently disable the read-write code paths that rely on this property.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
StorageObjectRead,
StorageObjectWrite,
)
return isinstance(self.storage_object_cls, StorageObjectReadWrite)
return isinstance(
self.get_storage_object_cls(), StorageObjectRead
) and isinstance(self.get_storage_object_cls(), StorageObjectWrite)
StorageObjectRead,
StorageObjectWrite,
)
cls = self.get_storage_object_cls()
return issubclass(cls, StorageObjectRead) and issubclass(cls, StorageObjectWrite)
🤖 Prompt for AI Agents
In snakemake_interface_storage_plugins/storage_provider.py around lines 165 to
172, the is_read_write property incorrectly uses isinstance() on a class
returned by get_storage_object_cls(), which always returns False. Replace
isinstance() with issubclass() to correctly check if the class is a subclass of
StorageObjectRead and StorageObjectWrite. Also, call get_storage_object_cls()
once, store the result in a variable, and use that variable for both subclass
checks to avoid redundant calls.

@classmethod
def get_storage_object_cls(cls):
Expand Down
Loading