Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 31 additions & 13 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,27 +43,45 @@ pip install numpy-flight

### Basic Setup

We introduce the Baseclass 'Server':

```python
import numpy as np
from np.flight import Client
>>> from np.flight import Server

>>> class TestServer(Server):
... def f(self, matrices):
... self.logger.info(f"{matrices.keys()}")
... # Simple implementation for testing - just return the input
... return {key : 2*value for key, value in matrices.items()}
```

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

The server can be started locally with

```python
>>> server = TestServer.start(host="127.0.0.1", port=5555)
```

### Sending Data
While the server is running we can use a client for computations

```python
# Prepare your NumPy arrays
data = {
'values': np.array([1, 2, 3, 4, 5]),
'labels': np.array(['a', 'b', 'c', 'd', 'e'])
}
>>> import numpy as np
>>> from np.flight import Client

# Send data to the server
client.write('store_data', data)
>>> with Client(location="grpc://127.0.0.1:5555") as client:
... output = client.compute(command="compute", data={"input": np.array([1,2,3])})

>>> print(output["input"])
[2 4 6]

```

```python
server.shutdown()
```

### Retrieving Data
Expand Down
3 changes: 2 additions & 1 deletion src/np/flight/numpy_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,8 @@ def start(cls, host="0.0.0.0", port=8080, logger=None, **kwargs): # pragma: no
"""
server = cls(host=host, port=port, logger=logger, **kwargs) # Instantiate the server.
server.logger.info(f"Starting {cls} Flight server on port {port}...") # Log the server start.
server.serve() # Start the server to handle incoming requests.
# server.serve() # Start the server to handle incoming requests.
return server

@abstractmethod
def f(self, matrices: dict[str, np.ndarray]) -> dict[str, np.ndarray]: ... # pragma: no cover
7 changes: 7 additions & 0 deletions src/tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,18 @@
# limitations under the License.
"""global fixtures"""

from pathlib import Path

import numpy as np
import pyarrow as pa
import pytest


@pytest.fixture(name="root_dir")
def root_fixture() -> Path:
return Path(__file__).parent.parent.parent


@pytest.fixture
def test_data():
"""
Expand Down
39 changes: 39 additions & 0 deletions src/tests/test_docs.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
import doctest
import os
import re

import pytest


@pytest.fixture()
def docstring(root_dir):
# Read the README.md file
with open(root_dir / "README.md") as f:
content = f.read()

# Extract Python code blocks (assuming they are in triple backticks)
blocks = re.findall(r"```python(.*?)```", content, re.DOTALL)

code = "\n".join(blocks).strip()

# Add a docstring wrapper for doctest to process the code
docstring = f"\n{code}\n"

return docstring


def test_blocks(root_dir, docstring, capfd):
os.chdir(root_dir)

try:
doctest.run_docstring_examples(docstring, globals())
except doctest.DocTestFailure as e:
# If a DocTestFailure occurs, capture it and manually fail the test
pytest.fail(f"Doctests failed: {e}")

# Capture the output after running doctests
captured = capfd.readouterr()

# If there is any output (error message), fail the test
if captured.out:
pytest.fail(f"Doctests failed with the following output:\n{captured.out} and \n{docstring}")