From 8b3dcf2bcbd1b7d8f8d425b463a364ff7ae0e0f6 Mon Sep 17 00:00:00 2001 From: Eugene Date: Fri, 6 Mar 2026 09:45:14 -0600 Subject: [PATCH 1/3] bump version to 1.0.3 and clean up code formatting --- build_and_push.sh | 2 +- montycat/store_classes/inmemory.py | 19 ++++++++----------- montycat/store_classes/kv.py | 11 +++-------- montycat/store_classes/persistent.py | 3 --- 4 files changed, 12 insertions(+), 23 deletions(-) diff --git a/build_and_push.sh b/build_and_push.sh index e5deec2..d25135d 100755 --- a/build_and_push.sh +++ b/build_and_push.sh @@ -2,7 +2,7 @@ # Configuration PACKAGE_NAME="montycat" -VERSION="1.0.2" +VERSION="1.0.3" PYPI_TOKEN="${PYPI_TOKEN:-}" # Exit on any error diff --git a/montycat/store_classes/inmemory.py b/montycat/store_classes/inmemory.py index f56c998..af3a64b 100644 --- a/montycat/store_classes/inmemory.py +++ b/montycat/store_classes/inmemory.py @@ -38,15 +38,15 @@ async def clean_snapshots_for_keyspace(cls): query = orjson.dumps({ "raw": [ - "clean-snapshots-for-keyspace", - "store", cls.store, - "keyspace", cls.keyspace, + "clean-snapshots-for-keyspace", + "store", cls.store, + "keyspace", cls.keyspace, ], "credentials": [cls.username, cls.password] }) return await cls._run_query(query) - + @classmethod async def stop_snapshots_for_keyspace(cls): """ @@ -67,7 +67,7 @@ async def stop_snapshots_for_keyspace(cls): }) return await cls._run_query(query) - + @classmethod async def insert_custom_key(cls, custom_key: str, expire_sec: int = 0): """ @@ -79,13 +79,13 @@ async def insert_custom_key(cls, custom_key: str, expire_sec: int = 0): """ if not custom_key: raise ValueError("No custom key provided for insertion.") - + custom_key_converted = convert_custom_key(custom_key) cls.command = "insert_custom_key" query = convert_to_binary_query(cls, key=custom_key_converted, expire_sec=expire_sec) return await cls._run_query(query) - + @classmethod async def insert_custom_key_value(cls, custom_key: str, value: dict, expire_sec: int = 0): """ @@ -95,7 +95,7 @@ async def insert_custom_key_value(cls, custom_key: str, value: dict, expire_sec: expire_sec: The number of seconds before the inserted value expires. Returns: True if the insert operation was successful. Class 'str' if the insert operation failed. - + """ if not value: raise ValueError("No value provided for insertion.") @@ -185,9 +185,6 @@ async def get_keys(cls, volumes: list = [], latest_volume: bool = False): A list of keys in the store. Class 'str' if the get operation failed. """ - if latest_volume and len(volumes) > 0: - raise ValueError("Select either latest volume or volumes list, not both.") - cls.command = "get_keys" query = convert_to_binary_query(cls, volumes=volumes, latest_volume=latest_volume) diff --git a/montycat/store_classes/kv.py b/montycat/store_classes/kv.py index 8c807f7..9f478fd 100644 --- a/montycat/store_classes/kv.py +++ b/montycat/store_classes/kv.py @@ -234,24 +234,19 @@ async def get_bulk( Raises: ValueError: If both `bulk_keys` and `bulk_custom_keys` are empty and neither `volumes` nor `latest_volume` is specified. - ValueError: If both `pointers_metadata` and `with_pointers` are True. """ - if pointers_metadata and with_pointers: - raise ValueError("You select both pointers value and pointers metadata. Choose one") - if len(bulk_custom_keys) > 0: bulk_custom_keys = convert_custom_keys(bulk_custom_keys) bulk_keys += bulk_custom_keys selected_options = sum([ bool(bulk_keys), - bool(volumes), - bool(latest_volume) + bool(volumes and len(volumes) > 0) or latest_volume, ]) if selected_options != 1: - raise ValueError("Multiple conflicting options provided. Please provide exactly one of the following: keys, volumes, or latest volume.") + raise ValueError("Multiple conflicting options provided. Please provide keys or volumes/latest volume.") cls.command = "get_bulk" cls.limit_output = handle_limit(limit) @@ -279,7 +274,7 @@ async def update_bulk(cls, bulk_keys_values: dict = {}, bulk_custom_keys_values: ValueError: If neither `bulk_keys_values` nor `bulk_custom_keys_values` is provided. """ - if not bulk_keys_values: + if not bulk_keys_values and not bulk_custom_keys_values: raise ValueError("No key-value pairs provided for update.") if len(bulk_custom_keys_values) > 0: diff --git a/montycat/store_classes/persistent.py b/montycat/store_classes/persistent.py index b7912d0..3081c52 100644 --- a/montycat/store_classes/persistent.py +++ b/montycat/store_classes/persistent.py @@ -153,9 +153,6 @@ async def get_keys(cls, limit: Union[list, int] = [], volumes: list[str] = [], l A list of keys in the store. Class 'str' if the get operation failed. """ - if latest_volume and len(volumes) > 0: - raise ValueError("Select either latest volume or volumes list, not both.") - cls.limit_output = handle_limit(limit) cls.command = "get_keys" From 58fab5173cf4df30322d10ae50aee4cb1b342be3 Mon Sep 17 00:00:00 2001 From: Eugene Date: Fri, 6 Mar 2026 16:27:15 -0600 Subject: [PATCH 2/3] validate input parameters for key retrieval and keyspace creation --- montycat/store_classes/inmemory.py | 9 +++++++++ montycat/store_classes/kv.py | 4 ++-- montycat/store_classes/persistent.py | 3 +++ 3 files changed, 14 insertions(+), 2 deletions(-) diff --git a/montycat/store_classes/inmemory.py b/montycat/store_classes/inmemory.py index af3a64b..152b064 100644 --- a/montycat/store_classes/inmemory.py +++ b/montycat/store_classes/inmemory.py @@ -185,6 +185,9 @@ async def get_keys(cls, volumes: list = [], latest_volume: bool = False): A list of keys in the store. Class 'str' if the get operation failed. """ + if not latest_volume and not volumes: + raise ValueError("Please provide keys or volumes/latest volume.") + cls.command = "get_keys" query = convert_to_binary_query(cls, volumes=volumes, latest_volume=latest_volume) @@ -192,6 +195,12 @@ async def get_keys(cls, volumes: list = [], latest_volume: bool = False): @classmethod async def create_keyspace(cls): + """ + Create a keyspace in the store. + + Returns: + True if the keyspace was created successfully. Class 'str' if the keyspace creation failed. + """ query = orjson.dumps({ "raw": [ diff --git a/montycat/store_classes/kv.py b/montycat/store_classes/kv.py index 9f478fd..e1acad6 100644 --- a/montycat/store_classes/kv.py +++ b/montycat/store_classes/kv.py @@ -242,11 +242,11 @@ async def get_bulk( selected_options = sum([ bool(bulk_keys), - bool(volumes and len(volumes) > 0) or latest_volume, + bool(volumes and len(volumes) > 0) or latest_volume or bool(limit and len(limit) > 0), ]) if selected_options != 1: - raise ValueError("Multiple conflicting options provided. Please provide keys or volumes/latest volume.") + raise ValueError("Please provide keys or volumes/latest volume or limit.") cls.command = "get_bulk" cls.limit_output = handle_limit(limit) diff --git a/montycat/store_classes/persistent.py b/montycat/store_classes/persistent.py index 3081c52..ffacdb4 100644 --- a/montycat/store_classes/persistent.py +++ b/montycat/store_classes/persistent.py @@ -153,6 +153,9 @@ async def get_keys(cls, limit: Union[list, int] = [], volumes: list[str] = [], l A list of keys in the store. Class 'str' if the get operation failed. """ + if not volumes and not latest_volume and not limit: + raise ValueError("Please provide keys or volumes/latest volume or limit.") + cls.limit_output = handle_limit(limit) cls.command = "get_keys" From 49f6dc0bfcc9fb87ded2c568948b7a1839d5a892 Mon Sep 17 00:00:00 2001 From: Eugene Date: Fri, 6 Mar 2026 17:05:17 -0600 Subject: [PATCH 3/3] refine limit validation logic in generic_kv and persistent_kv classes --- montycat/store_classes/kv.py | 7 +++---- montycat/store_classes/persistent.py | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) diff --git a/montycat/store_classes/kv.py b/montycat/store_classes/kv.py index e1acad6..f693406 100644 --- a/montycat/store_classes/kv.py +++ b/montycat/store_classes/kv.py @@ -242,7 +242,7 @@ async def get_bulk( selected_options = sum([ bool(bulk_keys), - bool(volumes and len(volumes) > 0) or latest_volume or bool(limit and len(limit) > 0), + bool(volumes and len(volumes) > 0) or latest_volume or bool(limit and len(limit) > 0 and (limit[0] != 0 or limit[1] != 0)), ]) if selected_options != 1: @@ -319,6 +319,8 @@ async def lookup_values_where(cls, limit: Union[int, list] = 0, with_pointers: b Args: limit (int, optional): The maximum number of results to return. If 0, no limit is applied. Default is 0. with_pointers (bool, optional): If True, the query will include pointers in the result. Default is False. + key_included (bool, optional): If True, the query will include the keys in the result. Default is False. + pointers_metadata (bool, optional): If True, the query will include metadata about the pointers. Default is False. filters (dict): The filtering criteria for the lookup. These are field-value pairs that the values should match. Returns: @@ -328,9 +330,6 @@ async def lookup_values_where(cls, limit: Union[int, list] = 0, with_pointers: b ValueError: If no filters are provided. """ - if pointers_metadata and with_pointers: - raise ValueError("You select both pointers value and pointers metadata. Choose one") - if schema: cls.schema = str(schema) else: diff --git a/montycat/store_classes/persistent.py b/montycat/store_classes/persistent.py index ffacdb4..23f5e7b 100644 --- a/montycat/store_classes/persistent.py +++ b/montycat/store_classes/persistent.py @@ -153,7 +153,7 @@ async def get_keys(cls, limit: Union[list, int] = [], volumes: list[str] = [], l A list of keys in the store. Class 'str' if the get operation failed. """ - if not volumes and not latest_volume and not limit: + if not volumes and not latest_volume and not limit and (not isinstance(limit, list) or len(limit) != 2 or (limit[0] == 0 and limit[1] == 0)): raise ValueError("Please provide keys or volumes/latest volume or limit.") cls.limit_output = handle_limit(limit)