Skip to content

Commit 84f5193

Browse files
authored
Merge pull request #57 from tharropoulos/fix/node-initialization
fix: node initialization using a url string
2 parents 5b9d310 + f01084b commit 84f5193

5 files changed

Lines changed: 79 additions & 14 deletions

File tree

pytest.ini

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
[pytest]
2+
pythonpath = src

requirements.txt

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1,13 @@
1-
requests==2.22.0
1+
certifi==2024.7.4
2+
chardet==3.0.4
3+
charset-normalizer==3.3.2
4+
idna==2.8
5+
iniconfig==2.0.0
6+
mypy==1.11.0
7+
mypy-extensions==1.0.0
8+
packaging==24.1
9+
pluggy==1.5.0
10+
pytest==8.3.2
11+
requests==2.32.3
12+
typing_extensions==4.12.2
13+
urllib3==2.2.2

src/typesense/configuration.py

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,17 @@
1+
from typing import Literal
12
from .exceptions import ConfigError
23
from .logger import logger
34
from urllib.parse import urlparse
45

5-
class Node(object):
6-
def __init__(self, url):
7-
parsed = urlparse(url);
8-
if not parsed.hostname:
9-
raise ConfigError('Node URL does not contain the host name.')
10-
if not parsed.port:
11-
raise ConfigError('Node URL does not contain the port.')
12-
if not parsed.scheme:
13-
raise ConfigError('Node URL does not contain the protocol.')
14-
self.__init__(parsed.hostname, parsed.port, parsed.path, parsed.scheme)
156

16-
def __init__(self, host, port, path, protocol):
7+
class Node(object):
8+
def __init__(
9+
self,
10+
host: str,
11+
port: str | int,
12+
path: str,
13+
protocol: Literal['http', 'https'] | str,
14+
):
1715
self.host = host
1816
self.port = port
1917
self.path = path
@@ -22,6 +20,18 @@ def __init__(self, host, port, path, protocol):
2220
# Used to skip bad hosts
2321
self.healthy = True
2422

23+
@classmethod
24+
def from_url(cls, url: str) -> 'Node':
25+
parsed = urlparse(url)
26+
if not parsed.hostname:
27+
raise ConfigError('Node URL does not contain the host name.')
28+
if not parsed.port:
29+
raise ConfigError('Node URL does not contain the port.')
30+
if not parsed.scheme:
31+
raise ConfigError('Node URL does not contain the protocol.')
32+
33+
return cls(parsed.hostname, parsed.port, parsed.path, parsed.scheme)
34+
2535
def url(self):
2636
return '{0}://{1}:{2}{3}'.format(self.protocol, self.host, self.port, self.path)
2737

@@ -34,7 +44,7 @@ def __init__(self, config_dict):
3444
self.nodes = []
3545
for node_config in config_dict.get('nodes', []):
3646
if isinstance(node_config, str):
37-
node = Node(node_config)
47+
node = Node.from_url(node_config)
3848
else:
3949
node = Node(node_config['host'], node_config['port'], node_config.get('path', ''), node_config['protocol'])
4050
self.nodes.append(node)
@@ -43,7 +53,7 @@ def __init__(self, config_dict):
4353
if not nearest_node:
4454
self.nearest_node = None
4555
elif isinstance(nearest_node, str):
46-
self.nearest_node = Node(nearest_node)
56+
self.nearest_node = Node.from_url(nearest_node)
4757
else:
4858
self.nearest_node = Node(nearest_node['host'], nearest_node['port'], nearest_node.get('path', ''), nearest_node['protocol'])
4959

tests/__init__.py

Whitespace-only changes.

tests/node_test.py

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
import pytest
2+
3+
from src.typesense.configuration import Node
4+
from src.typesense.exceptions import ConfigError
5+
6+
7+
def test_node_initialization():
8+
node = Node(host="localhost", port=8108, path="/path", protocol="http")
9+
assert node.host == "localhost"
10+
assert node.port == 8108
11+
assert node.path == "/path"
12+
assert node.protocol == "http"
13+
assert node.healthy is True
14+
15+
16+
def test_node_from_url():
17+
node = Node.from_url("http://localhost:8108/path")
18+
assert node.host == "localhost"
19+
assert node.port == 8108
20+
assert node.path == "/path"
21+
assert node.protocol == "http"
22+
23+
24+
def test_node_from_url_missing_hostname():
25+
with pytest.raises(ConfigError, match="Node URL does not contain the host name."):
26+
Node.from_url("http://:8108/path")
27+
28+
29+
def test_node_from_url_missing_port():
30+
with pytest.raises(ConfigError, match="Node URL does not contain the port."):
31+
Node.from_url("http://localhost:/path")
32+
33+
34+
def test_node_from_url_missing_scheme():
35+
with pytest.raises(ConfigError, match="Node URL does not contain the protocol."):
36+
Node.from_url("//localhost:8108/path")
37+
38+
39+
def test_node_url():
40+
node = Node(host="localhost", port=8108, path="/path", protocol="http")
41+
assert node.url() == "http://localhost:8108/path"

0 commit comments

Comments
 (0)