Skip to content
Merged
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
3 changes: 1 addition & 2 deletions ravendb/documents/commands/batches.py
Original file line number Diff line number Diff line change
Expand Up @@ -130,8 +130,7 @@ def __enter__(self):
def __exit__(self, exc_type, exc_val, exc_tb):
pass

@property
def is_read_request(self):
def is_read_request(self) -> bool:
return False

def create_request(self, node: ServerNode) -> requests.Request:
Expand Down
1 change: 0 additions & 1 deletion ravendb/documents/commands/crud.py
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,6 @@ def prepare_request_with_multiple_ids(
def set_response(self, response: str, from_cache: bool) -> None:
self.result = GetDocumentsResult.from_json(json.loads(response)) if response is not None else None

@property
def is_read_request(self) -> bool:
return True

Expand Down
1 change: 0 additions & 1 deletion ravendb/documents/commands/multi_get.py
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,6 @@ def read_response(response_json: dict) -> GetResponse:

return get_response

@property
def is_read_request(self) -> bool:
return False

Expand Down
4 changes: 2 additions & 2 deletions ravendb/http/request_executor.py
Original file line number Diff line number Diff line change
Expand Up @@ -691,7 +691,7 @@ def choose_node_for_request(self, cmd: RavenCommand, session_info: SessionInfo)
if session_info is not None and session_info.can_use_load_balance_behavior:
return self._node_selector.get_node_by_session_id(session_info.session_id)

if not cmd.is_read_request:
if not cmd.is_read_request():
return self._node_selector.get_preferred_node()

if self.conventions.read_balance_behavior == ReadBalanceBehavior.NONE:
Expand Down Expand Up @@ -783,7 +783,7 @@ def _get_from_cache(
if (
use_cache
and command.can_cache
and command.is_read_request
and command.is_read_request()
and command.response_type == RavenCommandResponseType.OBJECT
):
return self._cache.get(url)
Expand Down
52 changes: 52 additions & 0 deletions ravendb/tests/raven_commands_tests/test_platform_contracts.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import unittest
import importlib
import inspect
import pkgutil
import ravendb

from ravendb.tests.test_base import TestBase


class TestPlatformContracts(TestBase):
def setUp(self):
super(TestPlatformContracts, self).setUp()

def tearDown(self):
super(TestPlatformContracts, self).tearDown()
TestBase.delete_all_topology_files()

def test_all_commands_expose_callable_is_read_request(self):
from ravendb.http.raven_command import RavenCommand

offenders = []
for mod in self._import_all_ravendb_modules():
for cls in self._iter_subclasses_in_module(mod, RavenCommand):
attr = getattr(cls, "is_read_request", None)
if isinstance(attr, property):
offenders.append(f"{cls.__module__}.{cls.__qualname__}")

if offenders:
self.fail("is_read_request must be a method on: " + ", ".join(offenders))

# private helpers
def _import_all_ravendb_modules(self):
for _, modname, _ in pkgutil.walk_packages(ravendb.__path__, ravendb.__name__ + "."):
if modname.startswith("ravendb.tests."):
continue
try:
yield importlib.import_module(modname)
except Exception:
continue

def _iter_subclasses_in_module(self, mod, base_cls):
for _, obj in inspect.getmembers(mod):
if inspect.isclass(obj) and issubclass(obj, base_cls) and obj is not base_cls:
yield obj
if inspect.isclass(obj):
for _, inner in inspect.getmembers(obj, inspect.isclass):
if issubclass(inner, base_cls) and inner is not base_cls:
yield inner


if __name__ == "__main__":
unittest.main