Skip to content

Commit e46bb6e

Browse files
authored
Merge pull request #20 from tschm/19-testing-the-readme
19 testing the readme
2 parents 8144265 + 5bcfbaf commit e46bb6e

File tree

4 files changed

+79
-14
lines changed

4 files changed

+79
-14
lines changed

README.md

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -43,27 +43,45 @@ pip install numpy-flight
4343

4444
### Basic Setup
4545

46+
We introduce the Baseclass 'Server':
47+
4648
```python
47-
import numpy as np
48-
from np.flight import Client
49+
>>> from np.flight import Server
50+
51+
>>> class TestServer(Server):
52+
... def f(self, matrices):
53+
... self.logger.info(f"{matrices.keys()}")
54+
... # Simple implementation for testing - just return the input
55+
... return {key : 2*value for key, value in matrices.items()}
56+
```
4957

50-
# Initialize the Flight client
51-
with Client('grpc://localhost:8815') as client:
52-
...
58+
All complexity is hidden in the class 'Server' which is itself a child
59+
of the pyarrrow's FlightServerBase class. It is enough to implement
60+
the method 'f' which is expecting a dictionary of numpy arrays. It will
61+
also return a dictionary of numpy arrays.
5362

63+
The server can be started locally with
64+
65+
```python
66+
>>> server = TestServer.start(host="127.0.0.1", port=5555)
5467
```
5568

56-
### Sending Data
69+
While the server is running we can use a client for computations
5770

5871
```python
59-
# Prepare your NumPy arrays
60-
data = {
61-
'values': np.array([1, 2, 3, 4, 5]),
62-
'labels': np.array(['a', 'b', 'c', 'd', 'e'])
63-
}
72+
>>> import numpy as np
73+
>>> from np.flight import Client
6474

65-
# Send data to the server
66-
client.write('store_data', data)
75+
>>> with Client(location="grpc://127.0.0.1:5555") as client:
76+
... output = client.compute(command="compute", data={"input": np.array([1,2,3])})
77+
78+
>>> print(output["input"])
79+
[2 4 6]
80+
81+
```
82+
83+
```python
84+
server.shutdown()
6785
```
6886

6987
### Retrieving Data

src/np/flight/numpy_server.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,8 @@ def start(cls, host="0.0.0.0", port=8080, logger=None, **kwargs): # pragma: no
111111
"""
112112
server = cls(host=host, port=port, logger=logger, **kwargs) # Instantiate the server.
113113
server.logger.info(f"Starting {cls} Flight server on port {port}...") # Log the server start.
114-
server.serve() # Start the server to handle incoming requests.
114+
# server.serve() # Start the server to handle incoming requests.
115+
return server
115116

116117
@abstractmethod
117118
def f(self, matrices: dict[str, np.ndarray]) -> dict[str, np.ndarray]: ... # pragma: no cover

src/tests/conftest.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,18 @@
1313
# limitations under the License.
1414
"""global fixtures"""
1515

16+
from pathlib import Path
17+
1618
import numpy as np
1719
import pyarrow as pa
1820
import pytest
1921

2022

23+
@pytest.fixture(name="root_dir")
24+
def root_fixture() -> Path:
25+
return Path(__file__).parent.parent.parent
26+
27+
2128
@pytest.fixture
2229
def test_data():
2330
"""

src/tests/test_docs.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import doctest
2+
import os
3+
import re
4+
5+
import pytest
6+
7+
8+
@pytest.fixture()
9+
def docstring(root_dir):
10+
# Read the README.md file
11+
with open(root_dir / "README.md") as f:
12+
content = f.read()
13+
14+
# Extract Python code blocks (assuming they are in triple backticks)
15+
blocks = re.findall(r"```python(.*?)```", content, re.DOTALL)
16+
17+
code = "\n".join(blocks).strip()
18+
19+
# Add a docstring wrapper for doctest to process the code
20+
docstring = f"\n{code}\n"
21+
22+
return docstring
23+
24+
25+
def test_blocks(root_dir, docstring, capfd):
26+
os.chdir(root_dir)
27+
28+
try:
29+
doctest.run_docstring_examples(docstring, globals())
30+
except doctest.DocTestFailure as e:
31+
# If a DocTestFailure occurs, capture it and manually fail the test
32+
pytest.fail(f"Doctests failed: {e}")
33+
34+
# Capture the output after running doctests
35+
captured = capfd.readouterr()
36+
37+
# If there is any output (error message), fail the test
38+
if captured.out:
39+
pytest.fail(f"Doctests failed with the following output:\n{captured.out} and \n{docstring}")

0 commit comments

Comments
 (0)