Skip to content

Commit 6866b78

Browse files
authored
Merge pull request #158 from poissoncorp/v5.2.0
RDBC-611 Python - subscriptions & RDBC-642 Python - document query test
2 parents 1a7e4b6 + 9c599d5 commit 6866b78

File tree

71 files changed

+5546
-432
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

71 files changed

+5546
-432
lines changed

README.md

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -113,6 +113,39 @@ Although new API isn't compatible with the previous one, it comes with **many im
113113
The client is still in the **beta** phase.
114114

115115
----
116+
### Demo
117+
118+
##### Working with secured server
119+
```python
120+
from ravendb import DocumentStore
121+
122+
URLS = ["https://raven.server.url"]
123+
DB_NAME = "SecuredDemo"
124+
CERT_PATH = "path\\to\\cert.pem"
125+
126+
127+
class User:
128+
def __init__(self, name: str, tag: str):
129+
self.name = name
130+
self.tag = tag
131+
132+
133+
store = DocumentStore(URLS, DB_NAME)
134+
store.certificate_pem_path = CERT_PATH
135+
store.initialize()
136+
user = User("Gracjan", "Admin")
137+
138+
with store.open_session() as session:
139+
session.store(user, "users/1")
140+
session.save_changes()
141+
142+
with store.open_session() as session:
143+
user = session.load("users/1", User)
144+
assert user.name == "Gracjan"
145+
assert user.tag == "Admin"
146+
```
147+
148+
---
116149

117150
#### RavenDB Documentation
118151
https://ravendb.net/docs/article-page/5.3/python

README_pypi.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,38 @@ Although new API isn't compatible with the previous one, it comes with **many im
107107

108108
The client is still in the **beta** phase.
109109

110+
----
111+
### Demo
112+
113+
##### Working with secured server
114+
```python
115+
from ravendb import DocumentStore
116+
117+
URLS = ["https://raven.server.url"]
118+
DB_NAME = "SecuredDemo"
119+
CERT_PATH = "path\\to\\cert.pem"
120+
121+
122+
class User:
123+
def __init__(self, name: str, tag: str):
124+
self.name = name
125+
self.tag = tag
126+
127+
128+
store = DocumentStore(URLS, DB_NAME)
129+
store.certificate_pem_path = CERT_PATH
130+
store.initialize()
131+
user = User("Gracjan", "Admin")
132+
133+
with store.open_session() as session:
134+
session.store(user, "users/1")
135+
session.save_changes()
136+
137+
with store.open_session() as session:
138+
user = session.load("users/1", User)
139+
assert user.name == "Gracjan"
140+
assert user.tag == "Admin"
141+
```
110142
----
111143
#### RavenDB Documentation
112144
https://ravendb.net/docs/article-page/5.3/python
Lines changed: 244 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,244 @@
1+
from __future__ import annotations
2+
3+
import json
4+
from datetime import timedelta
5+
from typing import Dict, Optional, List
6+
7+
import requests
8+
9+
from ravendb.documents.subscriptions.state import SubscriptionState
10+
from ravendb.http.topology import RaftCommand, ServerNode
11+
from ravendb.documents.conventions import DocumentConventions
12+
from ravendb.documents.subscriptions.options import SubscriptionCreationOptions, SubscriptionUpdateOptions
13+
from ravendb.http.raven_command import RavenCommand, VoidRavenCommand
14+
from ravendb.tools.utils import Utils
15+
from ravendb.util.util import RaftIdGenerator
16+
17+
18+
class CreateSubscriptionResult:
19+
def __init__(self, name: str):
20+
self.name = name
21+
22+
@classmethod
23+
def from_json(cls, json_dict: Dict) -> CreateSubscriptionResult:
24+
return CreateSubscriptionResult(json_dict["Name"])
25+
26+
27+
class CreateSubscriptionCommand(RavenCommand[CreateSubscriptionResult], RaftCommand):
28+
def __init__(
29+
self, conventions: DocumentConventions, options: SubscriptionCreationOptions, key: Optional[str] = None
30+
):
31+
super().__init__(CreateSubscriptionResult)
32+
if options is None:
33+
raise ValueError("Options cannot be None")
34+
self._options = options
35+
self._key = key
36+
37+
def create_request(self, node: ServerNode) -> requests.Request:
38+
url = f"{node.url}/databases/{node.database}/subscriptions"
39+
40+
if self._key is not None:
41+
url += "?id" + Utils.quote_key(self._key)
42+
43+
request = requests.Request("PUT")
44+
request.data = self._options.to_json()
45+
request.url = url
46+
return request
47+
48+
def set_response(self, response: Optional[str], from_cache: bool) -> None:
49+
self.result = CreateSubscriptionResult.from_json(json.loads(response))
50+
51+
def is_read_request(self) -> bool:
52+
return False
53+
54+
def get_raft_unique_request_id(self) -> str:
55+
return RaftIdGenerator.new_id()
56+
57+
58+
class TcpConnectionInfo:
59+
def __init__(
60+
self,
61+
port: Optional[int] = None,
62+
url: Optional[str] = None,
63+
certificate: Optional[str] = None,
64+
urls: Optional[List[str]] = None,
65+
node_tag: Optional[str] = None,
66+
):
67+
self.port = port
68+
self.url = url
69+
self.certificate = certificate
70+
self.urls = urls
71+
self.node_tag = node_tag
72+
73+
@classmethod
74+
def from_json(cls, json_dict: Dict) -> TcpConnectionInfo:
75+
return TcpConnectionInfo(
76+
json_dict.get("Port", None),
77+
json_dict.get("Url", None),
78+
json_dict.get("Certificate", None),
79+
json_dict.get("Urls", None),
80+
json_dict.get("NodeTag", None),
81+
)
82+
83+
84+
class GetTcpInfoForRemoteTaskCommand(RavenCommand[TcpConnectionInfo]):
85+
def __init__(self, tag: str, remote_database: str, remote_task: str, verify_database: bool = False):
86+
super(GetTcpInfoForRemoteTaskCommand, self).__init__(TcpConnectionInfo)
87+
if remote_database is None:
88+
raise ValueError("remote_database cannot be None")
89+
90+
self._remote_database = remote_database
91+
92+
if remote_task is None:
93+
raise ValueError("remote_task cannot be None")
94+
95+
self._remote_task = remote_task
96+
self._tag = tag
97+
self._verify_database = verify_database
98+
self.timeout = timedelta(seconds=15)
99+
self._requested_node: Optional[ServerNode] = None
100+
101+
def create_request(self, node: ServerNode) -> requests.Request:
102+
url = (
103+
f"{node.url}/info/remote-task/tcp?"
104+
f"database={self._url_encode(self._remote_database)}"
105+
f"&remote-task={self._url_encode(self._remote_task)}"
106+
f"&tag={self._url_encode(self._tag)}"
107+
)
108+
109+
if self._verify_database:
110+
url += "&verify-database=true"
111+
112+
self._requested_node = node
113+
return requests.Request("GET", url)
114+
115+
def set_response(self, response: Optional[str], from_cache: bool) -> None:
116+
if response is None:
117+
self._throw_invalid_response()
118+
119+
self.result = TcpConnectionInfo.from_json(json.loads(response))
120+
121+
@property
122+
def requested_node(self) -> ServerNode:
123+
return self._requested_node
124+
125+
def is_read_request(self) -> bool:
126+
return True
127+
128+
129+
class GetSubscriptionsResult:
130+
def __init__(self, results: Optional[List[SubscriptionState]] = None):
131+
self.results = results
132+
133+
@classmethod
134+
def from_json(cls, json_dict: Dict) -> GetSubscriptionsResult:
135+
return cls([SubscriptionState.from_json(result) for result in json_dict["Results"]])
136+
137+
138+
class GetSubscriptionsCommand(RavenCommand[List[SubscriptionState]]):
139+
def __init__(self, start: int, page_size: int):
140+
super(GetSubscriptionsCommand, self).__init__(list)
141+
self._start = start
142+
self._page_size = page_size
143+
144+
def create_request(self, node: ServerNode) -> requests.Request:
145+
url = f"{node.url}/databases/{node.database}/subscriptions?start={self._start}&pageSize={self._page_size}"
146+
147+
return requests.Request("GET", url)
148+
149+
def set_response(self, response: Optional[str], from_cache: bool) -> None:
150+
if response is None:
151+
self.result = None
152+
return
153+
154+
self.result = GetSubscriptionsResult.from_json(json.loads(response)).results
155+
156+
def is_read_request(self) -> bool:
157+
return True
158+
159+
160+
class DeleteSubscriptionCommand(VoidRavenCommand, RaftCommand):
161+
def __init__(self, name: str):
162+
super(DeleteSubscriptionCommand, self).__init__()
163+
self._name = name
164+
165+
def create_request(self, node: ServerNode) -> requests.Request:
166+
url = f"{node.url}/databases/{node.database}/subscriptions?taskName={self._name}"
167+
168+
return requests.Request("DELETE", url)
169+
170+
def get_raft_unique_request_id(self) -> str:
171+
return RaftIdGenerator.new_id()
172+
173+
174+
class GetSubscriptionStateCommand(RavenCommand[SubscriptionState]):
175+
def __init__(self, subscription_name: str):
176+
super(GetSubscriptionStateCommand, self).__init__(SubscriptionState)
177+
self._subscription_name = subscription_name
178+
179+
def is_read_request(self) -> bool:
180+
return True
181+
182+
def create_request(self, node: ServerNode) -> requests.Request:
183+
url = (
184+
f"{node.url}/databases/{node.database}/subscriptions/state?name={Utils.quote_key(self._subscription_name)}"
185+
)
186+
187+
return requests.Request("GET", url)
188+
189+
def set_response(self, response: Optional[str], from_cache: bool) -> None:
190+
self.result = SubscriptionState.from_json(json.loads(response))
191+
192+
193+
class DropSubscriptionConnectionCommand(VoidRavenCommand):
194+
def __init__(self, name: Optional[str] = None):
195+
super(DropSubscriptionConnectionCommand, self).__init__()
196+
self._name = name
197+
198+
def create_request(self, node: ServerNode) -> requests.Request:
199+
path = []
200+
path.append(node.url)
201+
path.append("/databases/")
202+
path.append(node.database)
203+
path.append("/subscriptions/drop")
204+
205+
if self._name and not self._name.isspace():
206+
path.append("?name=")
207+
path.append(Utils.quote_key(self._name))
208+
209+
url = "".join(path)
210+
return requests.Request("POST", url)
211+
212+
213+
class UpdateSubscriptionResult(CreateSubscriptionResult):
214+
pass
215+
216+
217+
class UpdateSubscriptionCommand(RavenCommand[UpdateSubscriptionResult], RaftCommand):
218+
def __init__(self, options: SubscriptionUpdateOptions):
219+
super(UpdateSubscriptionCommand, self).__init__(UpdateSubscriptionResult)
220+
self._options = options
221+
222+
def create_request(self, node: ServerNode) -> requests.Request:
223+
url = f"{node.url}/databases/{node.database}/subscriptions/update"
224+
225+
request = requests.Request("POST", url)
226+
request.data = self._options.to_json()
227+
228+
return request
229+
230+
def set_response(self, response: Optional[str], from_cache: bool) -> None:
231+
if from_cache:
232+
self.result = UpdateSubscriptionResult(self._options.name)
233+
return
234+
235+
if response is None:
236+
self._throw_invalid_response()
237+
238+
self.result = UpdateSubscriptionResult.from_json(json.loads(response))
239+
240+
def is_read_request(self) -> bool:
241+
return False
242+
243+
def get_raft_unique_request_id(self) -> str:
244+
return RaftIdGenerator.new_id()

ravendb/documents/indexes/definitions.py

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -59,12 +59,11 @@ def __str__(self):
5959

6060

6161
class FieldStorage(Enum):
62-
YES = " Yes"
62+
YES = "Yes"
6363
NO = "No"
6464

6565

6666
class FieldIndexing(Enum):
67-
YES = " Yes"
6867
NO = "No"
6968
SEARCH = "Search"
7069
EXACT = "Exact"
@@ -87,7 +86,7 @@ def __str__(self):
8786

8887

8988
class FieldTermVector(Enum):
90-
YES = " Yes"
89+
YES = "Yes"
9190
NO = "No"
9291
WITH_POSITIONS = "WithPositions"
9392
WITH_OFFSETS = "WithOffsets"
@@ -158,7 +157,7 @@ def to_json(self):
158157
"Storage": self.storage,
159158
"Indexing": self.indexing,
160159
"TermVector": self.term_vector,
161-
"Spatial": self.spatial,
160+
"Spatial": self.spatial.to_json() if self.spatial else None,
162161
"Analyzer": self.analyzer,
163162
"Suggestions": self.suggestions,
164163
}

0 commit comments

Comments
 (0)