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
14 changes: 9 additions & 5 deletions simvue/api/objects/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,10 +164,14 @@ def __init__(
)
)

self._headers: dict[str, str] = {
"Authorization": f"Bearer {self._user_config.server.token.get_secret_value()}",
"User-Agent": _user_agent or f"Simvue Python client {__version__}",
}
self._headers: dict[str, str] = (
{
"Authorization": f"Bearer {self._user_config.server.token.get_secret_value()}",
"User-Agent": _user_agent or f"Simvue Python client {__version__}",
}
if not self._offline
else {}
)

self._staging: dict[str, typing.Any] = {}

Expand Down Expand Up @@ -423,7 +427,7 @@ def _post(self, is_json: bool = True, **kwargs) -> dict[str, typing.Any]:

_json_response = get_json_from_response(
response=_response,
expected_status=[http.HTTPStatus.OK],
expected_status=[http.HTTPStatus.OK, http.HTTPStatus.CONFLICT],
scenario=f"Creation of {self._label}",
)

Expand Down
12 changes: 8 additions & 4 deletions simvue/config/parameters.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,19 +21,23 @@


class ServerSpecifications(pydantic.BaseModel):
url: pydantic.AnyHttpUrl
token: pydantic.SecretStr
url: pydantic.AnyHttpUrl | None
token: pydantic.SecretStr | None

@pydantic.field_validator("url")
@classmethod
def url_to_api_url(cls, v: typing.Any) -> str:
def url_to_api_url(cls, v: typing.Any) -> str | None:
if not v:
return
if f"{v}".endswith("/api"):
return f"{v}"
_url = URL(f"{v}") / "api"
return f"{_url}"

@pydantic.field_validator("token")
def check_token(cls, v: typing.Any) -> str:
def check_token(cls, v: typing.Any) -> str | None:
if not v:
return
value = v.get_secret_value()
if not (expiry := get_expiry(value)):
raise AssertionError("Failed to parse Simvue token - invalid token form")
Expand Down
4 changes: 2 additions & 2 deletions simvue/config/user.py
Original file line number Diff line number Diff line change
Expand Up @@ -212,10 +212,10 @@ def fetch(

_run_mode = mode or _config_dict["run"].get("mode") or "online"

if not _server_url:
if not _server_url and _run_mode != "offline":
raise RuntimeError("No server URL was specified")

if not _server_token:
if not _server_token and _run_mode != "offline":
raise RuntimeError("No server token was specified")

_config_dict["server"]["token"] = _server_token
Expand Down
33 changes: 19 additions & 14 deletions simvue/run.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,8 +31,8 @@

from simvue.api.objects.alert.base import AlertBase
from simvue.api.objects.alert.fetch import Alert
from simvue.api.objects.folder import Folder, get_folder_from_path
from simvue.exception import ObjectNotFoundError, SimvueRunError
from simvue.api.objects.folder import Folder
from simvue.exception import SimvueRunError
from simvue.utilities import prettify_pydantic


Expand Down Expand Up @@ -185,9 +185,13 @@ def __init__(
if self._user_config.metrics.resources_metrics_interval < 1
else self._user_config.metrics.resources_metrics_interval
)
self._headers: dict[str, str] = {
"Authorization": f"Bearer {self._user_config.server.token.get_secret_value()}"
}
self._headers: dict[str, str] = (
{
"Authorization": f"Bearer {self._user_config.server.token.get_secret_value()}"
}
if mode != "offline"
else {}
)
self._sv_obj: RunObject | None = None
self._pid: int | None = 0
self._shutdown_event: threading.Event | None = None
Expand Down Expand Up @@ -419,7 +423,9 @@ def _create_dispatch_callback(
if self._user_config.run.mode == "online" and not self._id:
raise RuntimeError("Expected identifier for run")

if not self._user_config.server.url or not self._sv_obj:
if (
self._user_config.run.mode != "offline" and not self._user_config.server.url
) or not self._sv_obj:
raise RuntimeError("Cannot commence dispatch, run not initialised")

def _dispatch_callback(
Expand Down Expand Up @@ -621,13 +627,10 @@ def init(

self._term_color = not no_color

try:
self._folder = get_folder_from_path(path=folder)
except ObjectNotFoundError:
self._folder = Folder.new(
path=folder, offline=self._user_config.run.mode == "offline"
)
self._folder.commit() # type: ignore
self._folder = Folder.new(
path=folder, offline=self._user_config.run.mode == "offline"
)
self._folder.commit() # type: ignore

if isinstance(visibility, str) and visibility not in ("public", "tenant"):
self._error(
Expand All @@ -638,7 +641,9 @@ def init(
self._error("invalid mode specified, must be online, offline or disabled")
return False

if not self._user_config.server.token or not self._user_config.server.url:
if self._user_config.run.mode != "offline" and (
not self._user_config.server.token or not self._user_config.server.url
):
self._error(
"Unable to get URL and token from environment variables or config file"
)
Expand Down