Skip to content
Draft
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
2 changes: 1 addition & 1 deletion .github/workflows/python-package.yml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ jobs:
cache: "poetry"
- run: poetry install
- run: >
poetry run pytest
poetry run pytest -vv
-m integration
--cloud-api-key "${{ secrets.CLOUD_API_KEY }}"
--enterprise-uri "https://test-api.lifecyclesolutions.ni.com" --enterprise-api-key "${{ secrets.ENTERPRISE_API_KEY }}"
Expand Down
12 changes: 7 additions & 5 deletions nisystemlink/clients/notebook/_notebook_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
)
from nisystemlink.clients.core.helpers._iterator_file_like import IteratorFileLike
from requests.models import Response
from uplink import Part, Path, retry
from uplink import Part, Path, multipart, retry

from . import models

Expand Down Expand Up @@ -70,6 +70,7 @@ def get_notebook(self, id: str) -> models.NotebookMetadata:
"""
...

@multipart
@put("ninotebook/v1/notebook/{id}")
def __update_notebook(
self,
Expand Down Expand Up @@ -115,8 +116,8 @@ def update_notebook(
"""
metadata_io = None
if metadata is not None:
metadata_str = metadata.json()
metadata_io = io.BytesIO(metadata_str.encode("utf-8"))
metadata_str = metadata.json(by_alias=True, exclude_unset=True)
metadata_io = io.BytesIO(metadata_str.encode("ascii"))

return self.__update_notebook(
id=id,
Expand All @@ -137,6 +138,7 @@ def delete_notebook(self, id: str) -> None:
"""
...

@multipart
@post("ninotebook/v1/notebook")
def __create_notebook(
self,
Expand Down Expand Up @@ -176,9 +178,9 @@ def create_notebook(
ApiException: if unable to communicate with the ``/ninotebook`` service or provided invalid
arguments.
"""
metadata_str = metadata.json()
metadata_str = metadata.json(by_alias=True, exclude_unset=True)

metadata_io = io.BytesIO(metadata_str.encode("utf-8"))
metadata_io = io.BytesIO(metadata_str.encode("ascii"))
return self.__create_notebook(
metadata=metadata_io,
content=content,
Expand Down
2 changes: 2 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ markers = [
"slow: mark a test as a slow test",
"focus: focus a specific test during development",
]
log_cli = "True"
log_cli_level = "INFO"

[tool.black]
exclude = ".*\\.pyi"
Expand Down
53 changes: 41 additions & 12 deletions tests/integration/notebook/test_notebook_client.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import logging
import string
from random import choices
import typing

import pytest
import responses
Expand Down Expand Up @@ -31,7 +33,9 @@ def random_filename() -> str:
"""Generate a random filename for each test in test class."""
rand_file_name = "".join(choices(string.ascii_letters + string.digits, k=10))

return f"{PREFIX}{rand_file_name}.ipynb"
name = f"{PREFIX}{rand_file_name}.ipynb"
logging.info(f"Random filename: {name}")
return name


@pytest.fixture()
Expand All @@ -45,7 +49,11 @@ def _create_notebook(

# file_bytes = file.read() # Read file as bytes
with open("tests/integration/notebook/sample_file.ipynb", "rb") as file:
notebook_response = client.create_notebook(metadata=metadata, content=file)
try:
notebook_response = client.create_notebook(metadata=metadata, content=file)
except ApiException as e:
logging.warning(f"Error creating notebook: {metadata.json(by_alias=True, exclude_unset=True)}")
raise
if cleanup:
notebook_ids.append(notebook_response.id)

Expand All @@ -58,6 +66,27 @@ def _create_notebook(
client.delete_notebook(id=notebook_id)


@pytest.fixture()
def update_notebook(client: NotebookClient):
"""Fixture to return a factory that updates a notebook."""
def _update_notebook(
id: str,
metadata: NotebookMetadata = None,
content: typing.BinaryIO = None,
) -> NotebookMetadata:

try:
notebook_response = client.update_notebook(id=id, metadata=metadata, content=content)
except ApiException as e:
if (metadata is not None):
logging.warning(f"Error updating notebook {id}: {metadata.json(by_alias=True, exclude_unset=True)}")
raise

return notebook_response

return _update_notebook


@pytest.mark.enterprise
@pytest.mark.integration
class TestNotebookClient:
Expand Down Expand Up @@ -117,7 +146,7 @@ def test__get_notebook_with_invalid_id__raises_ApiException_NotFound(self, clien
client.get_notebook(id="invalid_id")

def test__update_existing_notebook_metadata__update_notebook_metadata_succeeds(
self, client: NotebookClient, create_notebook, random_filename
self, client: NotebookClient, create_notebook, update_notebook, random_filename
):
metadata = NotebookMetadata(name=random_filename)
notebook = create_notebook(metadata=metadata)
Expand All @@ -127,21 +156,21 @@ def test__update_existing_notebook_metadata__update_notebook_metadata_succeeds(
notebook.name = new_name
notebook.properties = {"key": "value"}

response = client.update_notebook(id=notebook.id, metadata=notebook)
response = update_notebook(id=notebook.id, metadata=notebook)

assert response.id == notebook.id
assert response.name != random_filename
assert response.name == new_name
assert response.properties == notebook.properties

def test__update_existing_notebook_content__update_notebook_content_succeeds(
self, client: NotebookClient, create_notebook, random_filename
self, client: NotebookClient, create_notebook, update_notebook, random_filename
):
metadata = NotebookMetadata(name=random_filename)
notebook = create_notebook(metadata=metadata)

with open("tests/integration/notebook/sample_file.ipynb", "rb") as file:
response = client.update_notebook(id=notebook.id, content=file)
response = update_notebook(id=notebook.id, content=file)

assert response.id == notebook.id

Expand All @@ -153,17 +182,17 @@ def test__update_notebook_metadata_with_invalid_id__raises_ApiException_NotFound
client.update_notebook(id="invalid_id", metadata=metadata)

def test__update_notebook_content_with_invalid_file__raises_ApiException_BadRequest(
self, client: NotebookClient, create_notebook, random_filename
self, client: NotebookClient, create_notebook, update_notebook, random_filename
):
metadata = NotebookMetadata(name=random_filename)
notebook = create_notebook(metadata=metadata)

with open("tests/integration/notebook/test_notebook_client.py", "rb") as file:
with pytest.raises(ApiException, match="Bad Request"):
client.update_notebook(id=notebook.id, content=file)
update_notebook(id=notebook.id, content=file)

def test__update_notebook_content_with_duplicate_file_name__raises_ApiException_BadRequest(
self, client: NotebookClient, create_notebook, random_filename
self, client: NotebookClient, create_notebook, update_notebook, random_filename
):
metadata = NotebookMetadata(name=random_filename)
notebook = create_notebook(metadata=metadata)
Expand All @@ -172,17 +201,17 @@ def test__update_notebook_content_with_duplicate_file_name__raises_ApiException_
create_notebook(metadata=metadata)

with pytest.raises(ApiException, match="409 Conflict"):
client.update_notebook(id=notebook.id, metadata=notebook)
update_notebook(id=notebook.id, metadata=notebook)

def test__update_notebook_with_invalid_workspace__raises_ApiException_BadRequest(
self, client: NotebookClient, create_notebook, random_filename
self, client: NotebookClient, create_notebook, update_notebook, random_filename
):
metadata = NotebookMetadata(name=random_filename)
notebook = create_notebook(metadata=metadata)

metadata.workspace = "invalid_workspace"
with pytest.raises(ApiException, match="Bad Request"):
client.update_notebook(id=notebook.id, metadata=metadata)
update_notebook(id=notebook.id, metadata=metadata)

def test__delete_notebook_with_valid_id__notebook_should_delete_successfully(
self, client: NotebookClient, create_notebook, random_filename
Expand Down
Loading