montycat 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.1
2
+ Name: montycat
3
+ Version: 0.1.1
4
+ Summary: A Python client for MontyCat, NoSQL store utilizing Data Mesh architecture.
5
+ Author: MontyGovernance
6
+ Author-email: eugene.and.monty@gmail.com
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: orjson
13
+ Requires-Dist: xxhash
14
+ Requires-Dist: asyncio
15
+
16
+ # MontyCat
17
+
18
+ **MontyCat** is a Python client for **MontyCat**, a high-performance, distributed NoSQL store designed with a cutting-edge Data Mesh architecture. This client empowers developers to seamlessly manage and query their data while leveraging the unparalleled flexibility and scalability offered by NoSQL databases within a decentralized data ownership paradigm.
19
+
20
+ ## Key Features
21
+
22
+ - **High Performance:** Harnesses MontyCat's advanced architecture for lightning-fast read and write operations.
23
+ - **Distributed Architecture:** Effortlessly connects to a distributed NoSQL database, enabling dynamic horizontal scalability across diverse data domains.
24
+ - **Data Mesh Design:** Innovatively utilizes a Data Mesh framework that empowers cross-functional teams to own, manage, and serve their own data, enhancing collaboration and eliminating bottlenecks.
25
+ - **Asynchronous Support:** Built on `asyncio` for ultra-responsive, non-blocking operations, enabling high concurrency and real-time data processing.
26
+ - **Meshing and Sharding:** Efficiently orchestrates data across multiple nodes with robust support for data meshing and sharding, optimizing resource utilization.
27
+ - **Memory Safety:** Implements state-of-the-art memory management practices, minimizing the risk of memory-related issues and enhancing stability.
28
+ - **Smart Data Governance:** Integrates intelligent governance features to ensure data quality and compliance across the distributed architecture.
29
+ - **Seamless Integration:** Offers a simple and intuitive API for effortless integration with your Python applications, reducing time-to-value.
30
+ - **Robust Documentation:** Comprehensive and user-friendly documentation to accelerate onboarding and maximize productivity.
31
+
32
+ ## Installation
33
+
34
+ You can install MontyCat using pip:
35
+
36
+ ```bash
37
+ pip install montycat
@@ -0,0 +1,22 @@
1
+ # MontyCat
2
+
3
+ **MontyCat** is a Python client for **MontyCat**, a high-performance, distributed NoSQL store designed with a cutting-edge Data Mesh architecture. This client empowers developers to seamlessly manage and query their data while leveraging the unparalleled flexibility and scalability offered by NoSQL databases within a decentralized data ownership paradigm.
4
+
5
+ ## Key Features
6
+
7
+ - **High Performance:** Harnesses MontyCat's advanced architecture for lightning-fast read and write operations.
8
+ - **Distributed Architecture:** Effortlessly connects to a distributed NoSQL database, enabling dynamic horizontal scalability across diverse data domains.
9
+ - **Data Mesh Design:** Innovatively utilizes a Data Mesh framework that empowers cross-functional teams to own, manage, and serve their own data, enhancing collaboration and eliminating bottlenecks.
10
+ - **Asynchronous Support:** Built on `asyncio` for ultra-responsive, non-blocking operations, enabling high concurrency and real-time data processing.
11
+ - **Meshing and Sharding:** Efficiently orchestrates data across multiple nodes with robust support for data meshing and sharding, optimizing resource utilization.
12
+ - **Memory Safety:** Implements state-of-the-art memory management practices, minimizing the risk of memory-related issues and enhancing stability.
13
+ - **Smart Data Governance:** Integrates intelligent governance features to ensure data quality and compliance across the distributed architecture.
14
+ - **Seamless Integration:** Offers a simple and intuitive API for effortless integration with your Python applications, reducing time-to-value.
15
+ - **Robust Documentation:** Comprehensive and user-friendly documentation to accelerate onboarding and maximize productivity.
16
+
17
+ ## Installation
18
+
19
+ You can install MontyCat using pip:
20
+
21
+ ```bash
22
+ pip install montycat
@@ -0,0 +1,4 @@
1
+ from .core.engine import Engine
2
+ from .core.schema import Schema, Pointer
3
+ from .core.limit import Limit
4
+ from .core.store import Store
File without changes
@@ -0,0 +1,101 @@
1
+ import asyncio
2
+ import orjson
3
+
4
+ class Engine:
5
+ def __init__(self, host: str, port: int, username: str, password: str, store_name: str):
6
+ self.host = host
7
+ self.port = port
8
+ self.username = username
9
+ self.password = password
10
+ self.store_name = store_name
11
+
12
+ async def send_data(host: str, port: int, string: str):
13
+ resp = None
14
+ writer = None
15
+
16
+ try:
17
+ reader, writer = await asyncio.open_connection(host, port)
18
+ writer.write(string + b"\n")
19
+ await writer.drain()
20
+
21
+ try:
22
+ resp = await asyncio.wait_for(reader.readuntil(b"\n"), timeout=120)
23
+ resp = resp.decode().strip()
24
+
25
+ try:
26
+ resp = recursive_parse_orjson(resp)
27
+ except Exception as parse_error:
28
+ print(f"Failed to parse response: {parse_error}")
29
+
30
+ except asyncio.TimeoutError:
31
+ resp = "Operation timed out"
32
+
33
+ except ConnectionRefusedError:
34
+ resp = "Connection refused"
35
+ except Exception as e:
36
+ resp = f"An unexpected error occurred: {e}"
37
+ finally:
38
+ if writer:
39
+ writer.close()
40
+ await writer.wait_closed()
41
+ return resp
42
+
43
+
44
+ def recursive_parse_orjson(data):
45
+ """
46
+ Recursively parses nested JSON strings in the provided data using orjson for faster parsing.
47
+
48
+ Args:
49
+ data: A Python object that may contain JSON strings, including nested structures.
50
+
51
+ Returns:
52
+ A fully parsed Python object with all nested JSON strings converted.
53
+ """
54
+ if isinstance(data, dict):
55
+ return {
56
+ key: recursive_parse_orjson(value)
57
+ for key, value in data.items()
58
+ }
59
+ elif isinstance(data, tuple):
60
+ return tuple(recursive_parse_orjson(element) if not element.isdigit() else element for element in data)
61
+ elif isinstance(data, list):
62
+ return [recursive_parse_orjson(element) if not element.isdigit() else element for element in data]
63
+ elif isinstance(data, str):
64
+ try:
65
+ parsed_data = orjson.loads(data)
66
+ return recursive_parse_orjson(parsed_data)
67
+ except orjson.JSONDecodeError:
68
+ return data
69
+
70
+ elif isinstance(data, (int, float)):
71
+ return data
72
+
73
+ else:
74
+ return data
75
+
76
+ # def recursive_parse_orjson(data):
77
+ # """
78
+ # Recursively parses nested JSON strings in the provided data using orjson for faster parsing.
79
+
80
+ # Args:
81
+ # data: A Python object that may contain JSON strings, including nested structures.
82
+
83
+ # Returns:
84
+ # A fully parsed Python object with all nested JSON strings converted.
85
+ # """
86
+ # if isinstance(data, dict):
87
+ # return {key: recursive_parse_orjson(value) for key, value in data.items()}
88
+ # elif isinstance(data, tuple):
89
+ # return tuple(recursive_parse_orjson(element) for element in data)
90
+ # elif isinstance(data, list):
91
+ # return [recursive_parse_orjson(element) for element in data]
92
+ # elif isinstance(data, str):
93
+ # try:
94
+ # # Attempt to parse the string as JSON
95
+ # parsed_data = orjson.loads(data)
96
+ # return recursive_parse_orjson(parsed_data)
97
+ # except orjson.JSONDecodeError:
98
+ # # Return the original string if it can't be parsed
99
+ # return data
100
+ # else:
101
+ # return data
@@ -0,0 +1,7 @@
1
+ class Limit:
2
+ def __init__(self, start: int = 0, stop: int = 0):
3
+ self.start = start
4
+ self.stop = stop
5
+
6
+ def return_limit(self):
7
+ return {"start": self.start, "stop": self.stop}
@@ -0,0 +1,75 @@
1
+ from typing import get_origin, get_args, get_type_hints, Union
2
+
3
+ class Pointer:
4
+ def __init__(self, **kwargs):
5
+
6
+ for key, value in kwargs.items():
7
+ setattr(self, key, [value[0].store_namespace, value[1]])
8
+
9
+ def __str__(self):
10
+ return str(self.__dict__)
11
+
12
+ def serialize(self):
13
+ return self.__dict__
14
+
15
+ class Schema:
16
+ def __init__(self, **kwargs):
17
+ hints = get_type_hints(self.__class__)
18
+ for key, value in kwargs.items():
19
+ setattr(self, key, value)
20
+ for attribute in hints:
21
+ if not hasattr(self, attribute):
22
+ setattr(self, attribute, None)
23
+ self.validate_types()
24
+
25
+ def __repr__(self):
26
+ return str(self.__dict__)
27
+
28
+ def __str__(self):
29
+ return str(self.__dict__)
30
+
31
+ def serialize(self):
32
+ if hasattr(self, "pointers"):
33
+ self.pointers = self.pointers.serialize()
34
+ for k, v in self.pointers.items():
35
+ if v[1].isdigit():
36
+ self.pointers[k] = [v[0].store_namespace, str(v[1])]
37
+
38
+ return self.__dict__
39
+
40
+ def validate_types(self):
41
+ hints = get_type_hints(self.__class__)
42
+ for attribute, expected_type in hints.items():
43
+ actual_value = getattr(self, attribute)
44
+
45
+ origin = get_origin(expected_type)
46
+
47
+
48
+ if origin is Union:
49
+
50
+ expected_types = get_args(expected_type)
51
+ if not isinstance(actual_value, expected_types) and actual_value is not None:
52
+ raise TypeError(
53
+ f"Attribute '{attribute}' should be one of types {expected_types}, "
54
+ f"but got '{type(actual_value).__name__}'"
55
+ )
56
+
57
+ elif origin is Pointer:
58
+ if not isinstance(actual_value, Pointer) and actual_value is not None:
59
+ raise TypeError(
60
+ f"Attribute '{attribute}' should be of type '{expected_type.__name__}', "
61
+ f"but got '{type(actual_value).__name__}'"
62
+ )
63
+
64
+ elif origin is None:
65
+ if not isinstance(actual_value, expected_type) and actual_value is not None:
66
+ raise TypeError(
67
+ f"Attribute '{attribute}' should be of type '{expected_type.__name__}', "
68
+ f"but got '{type(actual_value).__name__}'"
69
+ )
70
+ else:
71
+ if not isinstance(actual_value, origin) and actual_value is not None:
72
+ raise TypeError(
73
+ f"Attribute '{attribute}' should be of type '{expected_type}', "
74
+ f"but got '{type(actual_value).__name__}'"
75
+ )
@@ -0,0 +1,33 @@
1
+ from ..store_classes.kv import generic_kv
2
+
3
+ class Store:
4
+ class InMemory(generic_kv):
5
+ persistent = False
6
+ distributed = False
7
+
8
+ def __init__(self, *args, **kwargs):
9
+ super().__init__(*args, **kwargs)
10
+
11
+ class Distributed(generic_kv):
12
+ persistent = False
13
+ distributed = True
14
+
15
+ def __init__(self, *args, **kwargs):
16
+ super().__init__(*args, **kwargs)
17
+
18
+ class Persistent(generic_kv):
19
+ persistent = True
20
+ distributed = False
21
+
22
+ def __init__(self, *args, **kwargs):
23
+ super().__init__(*args, **kwargs)
24
+
25
+ class Distributed(generic_kv):
26
+ persistent = True
27
+ distributed = True
28
+
29
+ def __init__(self, *args, **kwargs):
30
+ super().__init__(*args, **kwargs)
31
+
32
+
33
+
File without changes
@@ -0,0 +1,221 @@
1
+ from ..core.engine import Engine, send_data
2
+ from ..core.schema import Pointer
3
+ from ..store_functions.store_generic_functions import handle_limit, connect_engine_, create_namespace_, drop_namespace_, drop_store_, show_store_properties_, convert_to_binary_query, convert_custom_key, convert_custom_keys, convert_custom_keys_values
4
+ import asyncio
5
+
6
+ class generic_kv:
7
+ store_name: str = ""
8
+ command: str = ""
9
+ persistent: bool = False
10
+ request: str = "store"
11
+ blockchain: bool = False
12
+ limit_output: dict = {}
13
+
14
+ @classmethod
15
+ def _run_query(cls, query: str):
16
+ return asyncio.run(send_data(cls.host, cls.port, query))
17
+
18
+ @classmethod
19
+ def insert_custom_key(cls, custom_key: str, expire_sec: int = 0):
20
+ """
21
+ Args:
22
+ custom_key: A custom key to insert into the store. This key can be used to retrieve the value later.
23
+ expire_sec: The number of seconds before the inserted value expires.
24
+ Returns:
25
+ True if the insert operation was successful. Class 'str' if the insert operation failed.
26
+ """
27
+ custom_key_converted = convert_custom_key(custom_key)
28
+ cls.command = "insert_custom_key"
29
+ query = convert_to_binary_query(cls, key=custom_key_converted, expire_sec=expire_sec)
30
+ return cls._run_query(query)
31
+
32
+ @classmethod
33
+ def insert_custom_key_value(cls, custom_key: str, value: dict, expire_sec: int = 0):
34
+ """
35
+ Args:
36
+ custom_key: A custom key to insert into the store. This key can be used to retrieve the value later.
37
+ value: A Python class / dict to insert into the store.
38
+ expire_sec: The number of seconds before the inserted value expires.
39
+ Returns:
40
+ True if the insert operation was successful. Class 'str' if the insert operation failed.
41
+
42
+ custom_key = "some_value"
43
+ value = {
44
+ "operation": 1,
45
+ "amount": 4500.0
46
+ }
47
+
48
+ """
49
+ custom_key_converted = convert_custom_key(custom_key)
50
+ cls.command = "insert_custom_key_value"
51
+ query = convert_to_binary_query(cls, key=custom_key_converted, value=value, expire_sec=expire_sec)
52
+ return cls._run_query(query)
53
+
54
+ @classmethod
55
+ def insert_value(cls, value: dict, expire_sec: int = 0):
56
+ """
57
+ Args:
58
+ value: A Python class / dict to insert into the store.
59
+ expire_sec: The number of seconds before the inserted value expires.
60
+ Returns:
61
+ Key number if the insert operation was successful. Class 'str' if the insert operation failed.
62
+ """
63
+ cls.command = "insert_value"
64
+ query = convert_to_binary_query(cls, value=value, expire_sec=expire_sec)
65
+ return cls._run_query(query)
66
+
67
+ @classmethod
68
+ def get_value(cls, key: int | str = "", custom_key: str = "", with_pointers: bool = False):
69
+
70
+ """
71
+ Args:
72
+ key: The key number of the value to retrieve.
73
+ custom_key: The custom key of the value to retrieve.
74
+ with_pointers: A boolean value that determines whether to include pointers (foreign values) in the output.
75
+ Returns:
76
+ The value associated with the key or custom key. Class 'str' if the get operation failed.
77
+ """
78
+ if len(custom_key) > 0:
79
+ key = convert_custom_key(custom_key)
80
+ cls.command = "get_value"
81
+ query = convert_to_binary_query(cls, key=key, with_pointers=with_pointers)
82
+ return cls._run_query(query)
83
+
84
+ @classmethod
85
+ def get_keys(cls, limit: list = []):
86
+ """
87
+ Args:
88
+ Limit: A list of two integers that determine the range of keys to retrieve.
89
+ Example: limit = [10, 20] will retrieve keys 10 to 20.
90
+ Returns:
91
+ A list of keys in the store. Class 'str' if the get operation failed.
92
+ """
93
+ lim = handle_limit(limit)
94
+ cls.command = "get_keys"
95
+ cls.limit_output = lim
96
+ query = convert_to_binary_query(cls)
97
+ return cls._run_query(query)
98
+
99
+ @classmethod
100
+ def delete_key(cls, key: int | str = "", custom_key: str = ""):
101
+
102
+ if len(custom_key) > 0:
103
+ key = convert_custom_key(custom_key)
104
+
105
+ cls.command = "delete_key"
106
+ query = convert_to_binary_query(cls, key=key)
107
+ return cls._run_query(query)
108
+
109
+ @classmethod
110
+ def update_value(cls, key: int | str = "", custom_key: str = "", **filters):
111
+
112
+ if len(custom_key) > 0:
113
+ key = convert_custom_key(custom_key)
114
+
115
+ cls.command = "update_value"
116
+ query = convert_to_binary_query(cls, key=key, value=filters)
117
+ print(query)
118
+ return cls._run_query(query)
119
+
120
+ @classmethod
121
+ def insert_bulk(cls, bulk_values: list, expire_sec: int = 0):
122
+ # bulk_values = [str(item) for item in bulk if len(bulk) > 0]
123
+ """
124
+ Args:
125
+ bulk_values: A list of Python objects to insert into the store.
126
+ expire_sec: The number of seconds before the inserted values expire.
127
+
128
+ Returns:
129
+ True if the bulk insert operation was successful.
130
+ List of values that were not inserted.
131
+ """
132
+ cls.command = "insert_bulk"
133
+ query = convert_to_binary_query(cls, bulk_values=bulk_values, expire_sec=expire_sec)
134
+ return cls._run_query(query)
135
+
136
+ @classmethod
137
+ def delete_bulk(cls, bulk_keys: list = [], bulk_custom_keys: list = []):
138
+
139
+ if len(bulk_custom_keys) > 0:
140
+ bulk_custom_keys = convert_custom_keys(bulk_custom_keys)
141
+ bulk_keys += bulk_custom_keys
142
+
143
+ cls.command = "delete_bulk"
144
+ query = convert_to_binary_query(cls, bulk_keys=bulk_keys)
145
+ return cls._run_query(query)
146
+
147
+ @classmethod
148
+ def get_bulk(cls, bulk_keys: list = [], bulk_custom_keys: list = [], limit: list = [], with_pointers: bool = False):
149
+
150
+ lim = handle_limit(limit)
151
+
152
+ if len(bulk_custom_keys) > 0:
153
+ bulk_custom_keys = convert_custom_keys(bulk_custom_keys)
154
+ bulk_keys += bulk_custom_keys
155
+
156
+ cls.command = "get_bulk"
157
+ cls.limit_output = lim
158
+ query = convert_to_binary_query(cls, bulk_keys=bulk_keys, with_pointers=with_pointers)
159
+ return cls._run_query(query)
160
+
161
+ @classmethod
162
+ def update_bulk(cls, bulk_keys_values: dict = {}, bulk_custom_keys_values: dict = {}):
163
+
164
+ if len(bulk_custom_keys_values) > 0:
165
+ bulk_custom_keys_values = convert_custom_keys_values(bulk_custom_keys_values)
166
+ bulk_keys_values = bulk_keys_values | bulk_custom_keys_values
167
+
168
+ # print(bulk_keys_values)
169
+
170
+ cls.command = "update_bulk"
171
+ query = convert_to_binary_query(cls, bulk_keys_values=bulk_keys_values)
172
+ return cls._run_query(query)
173
+
174
+ @classmethod
175
+ def lookup_keys_where(cls, limit: int = 0, **filters):
176
+
177
+ lim = handle_limit(limit)
178
+
179
+ cls.command = "lookup_keys"
180
+ cls.limit_output = lim
181
+ query = convert_to_binary_query(cls, search_criteria=filters)
182
+ return cls._run_query(query)
183
+
184
+ @classmethod
185
+ def lookup_values_where(cls, limit = 0, with_pointers: bool = False, **filters):
186
+
187
+ lim = handle_limit(limit)
188
+
189
+ cls.command = "lookup_values"
190
+ cls.limit_output = lim
191
+ query = convert_to_binary_query(cls, search_criteria=filters, with_pointers=with_pointers)
192
+ return cls._run_query(query)
193
+
194
+ @classmethod
195
+ def to_blockchain(cls, key: int):
196
+ cls.command = "blockchain"
197
+ cls.persistent = True
198
+ cls.blockchain = True
199
+ query = convert_to_binary_query(cls, key=key)
200
+ return cls._run_query(query)
201
+
202
+ @classmethod
203
+ def connect_engine(cls, engine: Engine) -> None:
204
+ connect_engine_(cls, engine)
205
+
206
+ @classmethod
207
+ def create_namespace(cls):
208
+ return create_namespace_(cls)
209
+
210
+ @classmethod
211
+ def drop_namespace(cls):
212
+ return drop_namespace_(cls)
213
+
214
+ @classmethod
215
+ def drop_store(cls):
216
+ drop_store_(cls)
217
+
218
+ @classmethod
219
+ def show_store_properties(cls):
220
+ show_store_properties_(cls)
221
+
File without changes
@@ -0,0 +1,123 @@
1
+ from ..core.engine import Engine, send_data
2
+ from ..core.limit import Limit
3
+ from ..core.schema import Pointer
4
+ import asyncio
5
+ import orjson
6
+ import xxhash
7
+
8
+ def connect_engine_(cls: type, engine: Engine) -> None:
9
+ cls.username = engine.username
10
+ cls.password = engine.password
11
+ cls.host = engine.host
12
+ cls.port = engine.port
13
+ cls.store_name = engine.store_name
14
+
15
+ def convert_custom_key(key: int | str) -> int:
16
+ return str(xxhash.xxh32(str(key)).intdigest())
17
+
18
+ def convert_custom_keys(keys: list) -> list:
19
+ return [convert_custom_key(key) for key in keys]
20
+
21
+ def convert_custom_keys_values(keys_values: dict) -> dict:
22
+ return {convert_custom_key(key): value for key, value in keys_values.items()}
23
+
24
+ def modify_pointers(value: dict):
25
+ if "pointers" in value:
26
+ try:
27
+ for k, v in value['pointers'].items():
28
+ if v[1].isdigit():
29
+ value['pointers'][k] = [v[0], str(v[1])]
30
+ else:
31
+ value['pointers'][k] = [v[0], convert_custom_key(v[1])]
32
+ return value
33
+ except:
34
+ raise ValueError("Pointer should be a valid hash key or custom key")
35
+ return value
36
+
37
+
38
+
39
+ def convert_to_binary_query(
40
+ cls: type,
41
+ key: str = "",
42
+ search_criteria: dict = {},
43
+ value: dict = {},
44
+ expire_sec: int = 0,
45
+ bulk_values: list = [],
46
+ bulk_keys: list = [],
47
+ bulk_keys_values: dict = {},
48
+ with_pointers: bool = False
49
+ ):
50
+
51
+ if len(value) > 0:
52
+ value = modify_pointers(value)
53
+
54
+ if len(bulk_values) > 0:
55
+ bulk_values = [str(modify_pointers(value)) for value in bulk_values]
56
+
57
+ if len(bulk_keys_values) > 0:
58
+ bulk_keys_values = {key: str(modify_pointers(value)) for key, value in bulk_keys_values.items()}
59
+
60
+ return orjson.dumps({
61
+ "request": cls.request,
62
+ "username": cls.username,
63
+ "password": cls.password,
64
+ "store_namespace": cls.store_namespace,
65
+ "store_name": cls.store_name,
66
+ "persistent": cls.persistent,
67
+ "distributed": cls.distributed,
68
+ "limit_output": cls.limit_output,
69
+ "key": str(key),
70
+ "value": str(value).replace("True", "true").replace("False", "false"),
71
+ "command": cls.command,
72
+ "expire": expire_sec,
73
+ "bulk_values": [str(value).replace("True", "true").replace("False", "false") for value in bulk_values],
74
+ "bulk_keys": bulk_keys,
75
+ "bulk_keys_values": {key: str(value).replace("True", "true").replace("False", "false") for key, value in bulk_keys_values.items()},
76
+ "blockchain": cls.blockchain,
77
+ "search_criteria": str(search_criteria).replace("True", "true").replace("False", "false"),
78
+ 'with_pointers': with_pointers,
79
+ })
80
+
81
+ def run_query(cls: type):
82
+ query = convert_to_binary_query(cls)
83
+ return asyncio.run(send_data(cls.host, cls.port, query))
84
+
85
+ def handle_limit(limit: list) -> dict:
86
+
87
+ limit_class = Limit()
88
+
89
+ if type(limit) == list:
90
+ if len(limit) > 1:
91
+ limit_class.start = limit[0]
92
+ limit_class.stop = limit[1]
93
+ elif len(limit) == 1:
94
+ limit_class.stop = limit[0]
95
+
96
+ return limit_class.return_limit()
97
+
98
+ def create_namespace_(cls: type) -> None:
99
+ cls.command = "create_namespace"
100
+ cls.request = "utils"
101
+ return run_query(cls)
102
+
103
+ def drop_namespace_(cls: type) -> None:
104
+ cls.command = "drop_namespace"
105
+ cls.request = "utils"
106
+ return run_query(cls)
107
+
108
+ def drop_store_(cls: type) -> None:
109
+ cls.command = "drop_store"
110
+ cls.request = "utils"
111
+ return print('DROP', cls.store_name)
112
+
113
+ def show_store_properties_(cls: type) -> None:
114
+ return print(
115
+ f"Store Name: {cls.store_name}\n"
116
+ f"Store Namespace: {cls.store_namespace}\n"
117
+ f"Persistent: {cls.persistent}\n"
118
+ f"Distributed: {cls.distributed}\n"
119
+ f"Host: {cls.host}\n"
120
+ f"Port: {cls.port}\n"
121
+ f"Username: {cls.username}\n"
122
+ f"Password: {cls.password}\n"
123
+ )
@@ -0,0 +1,37 @@
1
+ Metadata-Version: 2.1
2
+ Name: montycat
3
+ Version: 0.1.1
4
+ Summary: A Python client for MontyCat, NoSQL store utilizing Data Mesh architecture.
5
+ Author: MontyGovernance
6
+ Author-email: eugene.and.monty@gmail.com
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: License :: OSI Approved :: MIT License
9
+ Classifier: Operating System :: OS Independent
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ Requires-Dist: orjson
13
+ Requires-Dist: xxhash
14
+ Requires-Dist: asyncio
15
+
16
+ # MontyCat
17
+
18
+ **MontyCat** is a Python client for **MontyCat**, a high-performance, distributed NoSQL store designed with a cutting-edge Data Mesh architecture. This client empowers developers to seamlessly manage and query their data while leveraging the unparalleled flexibility and scalability offered by NoSQL databases within a decentralized data ownership paradigm.
19
+
20
+ ## Key Features
21
+
22
+ - **High Performance:** Harnesses MontyCat's advanced architecture for lightning-fast read and write operations.
23
+ - **Distributed Architecture:** Effortlessly connects to a distributed NoSQL database, enabling dynamic horizontal scalability across diverse data domains.
24
+ - **Data Mesh Design:** Innovatively utilizes a Data Mesh framework that empowers cross-functional teams to own, manage, and serve their own data, enhancing collaboration and eliminating bottlenecks.
25
+ - **Asynchronous Support:** Built on `asyncio` for ultra-responsive, non-blocking operations, enabling high concurrency and real-time data processing.
26
+ - **Meshing and Sharding:** Efficiently orchestrates data across multiple nodes with robust support for data meshing and sharding, optimizing resource utilization.
27
+ - **Memory Safety:** Implements state-of-the-art memory management practices, minimizing the risk of memory-related issues and enhancing stability.
28
+ - **Smart Data Governance:** Integrates intelligent governance features to ensure data quality and compliance across the distributed architecture.
29
+ - **Seamless Integration:** Offers a simple and intuitive API for effortless integration with your Python applications, reducing time-to-value.
30
+ - **Robust Documentation:** Comprehensive and user-friendly documentation to accelerate onboarding and maximize productivity.
31
+
32
+ ## Installation
33
+
34
+ You can install MontyCat using pip:
35
+
36
+ ```bash
37
+ pip install montycat
@@ -0,0 +1,19 @@
1
+ README.md
2
+ pyproject.toml
3
+ setup.py
4
+ montycat/__init__.py
5
+ montycat.egg-info/PKG-INFO
6
+ montycat.egg-info/SOURCES.txt
7
+ montycat.egg-info/dependency_links.txt
8
+ montycat.egg-info/not-zip-safe
9
+ montycat.egg-info/requires.txt
10
+ montycat.egg-info/top_level.txt
11
+ montycat/core/__init__.py
12
+ montycat/core/engine.py
13
+ montycat/core/limit.py
14
+ montycat/core/schema.py
15
+ montycat/core/store.py
16
+ montycat/store_classes/__init__.py
17
+ montycat/store_classes/kv.py
18
+ montycat/store_functions/__init__.py
19
+ montycat/store_functions/store_generic_functions.py
@@ -0,0 +1,3 @@
1
+ orjson
2
+ xxhash
3
+ asyncio
@@ -0,0 +1 @@
1
+ montycat
@@ -0,0 +1,4 @@
1
+ # pyproject.toml
2
+ [build-system]
3
+ requires = ["setuptools>=42", "wheel"]
4
+ build-backend = "setuptools.build_meta"
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,22 @@
1
+ # setup.py
2
+ from setuptools import setup, find_packages
3
+
4
+ setup(
5
+ name='montycat',
6
+ version='0.1.1',
7
+ description='A Python client for MontyCat, NoSQL store utilizing Data Mesh architecture.',
8
+ packages=find_packages(),
9
+ zip_safe=False,
10
+ long_description=open('README.md').read(),
11
+ long_description_content_type='text/markdown',
12
+ author='MontyGovernance',
13
+ author_email='eugene.and.monty@gmail.com',
14
+ include_package_data=True,
15
+ install_requires=['orjson', 'xxhash', 'asyncio'],
16
+ classifiers=[
17
+ 'Programming Language :: Python :: 3',
18
+ 'License :: OSI Approved :: MIT License',
19
+ 'Operating System :: OS Independent',
20
+ ],
21
+ python_requires='>=3.9',
22
+ )