Skip to content

Commit

Permalink
Implemented version control
Browse files Browse the repository at this point in the history
  • Loading branch information
khsrali committed Jul 31, 2024
1 parent 9d0dc5b commit 8459474
Show file tree
Hide file tree
Showing 4 changed files with 75 additions and 2 deletions.
11 changes: 10 additions & 1 deletion firecrest/AsyncClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
import firecrest.FirecrestException as fe
import firecrest.types as t
from firecrest.AsyncExternalStorage import AsyncExternalUpload, AsyncExternalDownload
from firecrest.utilities import time_block, slurm_state_completed
from firecrest.utilities import time_block, slurm_state_completed, async_validate_api_version_compatibility


if sys.version_info >= (3, 8):
Expand Down Expand Up @@ -247,6 +247,10 @@ def set_api_version(self, api_version: str) -> None:
"""Set the version of the api of firecrest. By default it will be assumed that you are
using version 1.13.1 or compatible. The version is parsed by the `packaging` library.
"""
if parse(api_version) < parse("1.13.0"):
raise ValueError(
f"API version {api_version} is no longer supported by this client"
)
self._api_version = parse(api_version)

async def close_session(self) -> None:
Expand Down Expand Up @@ -727,6 +731,7 @@ async def filesystems(self, system_name: Optional[str] = None) -> dict[str, List
return self._json_response([resp], 200)["out"]

# Utilities
@async_validate_api_version_compatibility(recursive=True)
async def list_files(
self, machine: str, target_path: str, show_hidden: bool = False,
recursive: bool = False
Expand Down Expand Up @@ -860,6 +865,7 @@ async def copy(self, machine: str, source_path: str, target_path: str) -> str:
self._json_response([resp], 201)
return target_path

@async_validate_api_version_compatibility()
async def compress(
self,
machine: str,
Expand Down Expand Up @@ -958,6 +964,7 @@ async def compress(

return target_path

@async_validate_api_version_compatibility()
async def extract(
self,
machine: str,
Expand Down Expand Up @@ -1812,6 +1819,7 @@ async def submit_copy_job(
result.update({"system": job_info[1]})
return result

@async_validate_api_version_compatibility()
async def submit_compress_job(
self,
machine: str,
Expand Down Expand Up @@ -1865,6 +1873,7 @@ async def submit_compress_job(
result.update({"system": job_info[1]})
return result

@async_validate_api_version_compatibility()
async def submit_extract_job(
self,
machine: str,
Expand Down
11 changes: 10 additions & 1 deletion firecrest/BasicClient.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
import firecrest.FirecrestException as fe
import firecrest.types as t
from firecrest.ExternalStorage import ExternalUpload, ExternalDownload
from firecrest.utilities import time_block, slurm_state_completed
from firecrest.utilities import time_block, slurm_state_completed, validate_api_version_compatibility

if sys.version_info >= (3, 8):
from typing import Literal
Expand Down Expand Up @@ -162,6 +162,10 @@ def set_api_version(self, api_version: str) -> None:
"""Set the version of the api of firecrest. By default it will be assumed that you are
using version 1.13.1 or compatible. The version is parsed by the `packaging` library.
"""
if parse(api_version) < parse("1.13.0"):
raise ValueError(
f"API version {api_version} is no longer supported by this client"
)
self._api_version = parse(api_version)

def log(self, level: int, msg: Any) -> None:
Expand Down Expand Up @@ -481,6 +485,7 @@ def filesystems(self, system_name: Optional[str] = None) -> dict[str, List[t.Fil
return self._json_response([resp], 200)["out"]

# Utilities
@validate_api_version_compatibility(recursive=True)
def list_files(
self, machine: str, target_path: str, show_hidden: bool = False,
recursive: bool = False
Expand Down Expand Up @@ -612,6 +617,7 @@ def copy(self, machine: str, source_path: str, target_path: str) -> str:
self._json_response([resp], 201)
return target_path

@validate_api_version_compatibility()
def compress(
self,
machine: str,
Expand Down Expand Up @@ -711,6 +717,7 @@ def compress(

return target_path

@validate_api_version_compatibility()
def extract(
self,
machine: str,
Expand Down Expand Up @@ -1726,6 +1733,7 @@ def external_download(self, machine: str, source_path: str) -> ExternalDownload:
self, self._json_response([resp], 201)["task_id"], [resp]
)

@validate_api_version_compatibility()
def submit_compress_job(
self,
machine: str,
Expand Down Expand Up @@ -1779,6 +1787,7 @@ def submit_compress_job(
result.update({"system": transfer_info[1]})
return result

@validate_api_version_compatibility()
def submit_extract_job(
self,
machine: str,
Expand Down
4 changes: 4 additions & 0 deletions firecrest/FirecrestException.py
Original file line number Diff line number Diff line change
Expand Up @@ -112,3 +112,7 @@ def __str__(self):
f"is exhausted. Update `polling_sleep_times` of the client "
f"to increase the number of polling attempts."
)


class NotImplementedOnAPIversion(Exception):
"""Exception raised when a feature is not developed yet for the current API version"""
51 changes: 51 additions & 0 deletions firecrest/utilities.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import time
from contextlib import contextmanager
import firecrest.FirecrestException as fe


@contextmanager
Expand Down Expand Up @@ -28,3 +29,53 @@ def slurm_state_completed(state):
return all(s in completion_states for s in state.split(','))

return False


def validate_api_version_compatibility(**expected_flags):
def decorator(func):
def wrapper(self, *args, **kwargs):
missing_features = missing_api_features.get(self._api_version, {}).get(func.__name__, [])

if 'ALL' in missing_features:
raise fe.NotImplementedOnAPIversion(f"All features for {func.__name__}"
" are not developed yet for the current API version.")

for flag, value in expected_flags.items():
if kwargs.get(flag) == value and flag in missing_features:
raise fe.NotImplementedOnAPIversion(f"The flag {flag}={value} is not developed"
" yet for {func.__name__} for the current API version.")

return func(self, *args, **kwargs)
return wrapper
return decorator


def async_validate_api_version_compatibility(**expected_flags):
def decorator(func):
async def wrapper(self, *args, **kwargs):
missing_features = missing_api_features.get(self._api_version, {}).get(func.__name__, [])

if 'ALL' in missing_features:
raise fe.NotImplementedOnAPIversion(f"All features for {func.__name__} are "
"not developed yet for the current API version.")

for flag, value in expected_flags.items():
if kwargs.get(flag) == value and flag in missing_features:
raise fe.NotImplementedOnAPIversion(f"The flag {flag}={value} is not developed"
" yet for {func.__name__} for the current API version.")

return await func(self, *args, **kwargs)
return wrapper
return decorator


missing_api_features = {
'1.15.0': {
'list_files': ['recursive'],
'compress': ['ALL'],
'extract': ['ALL'],
'submit_compress_job': ['ALL'],
'submit_extract_job': ['ALL']
},
'1.16.0': {},
}

0 comments on commit 8459474

Please sign in to comment.