diff --git a/.github/workflows/publish.yml b/.github/workflows/publish.yml index e645ab6..3e3c629 100644 --- a/.github/workflows/publish.yml +++ b/.github/workflows/publish.yml @@ -24,7 +24,7 @@ jobs: uses: actions/upload-artifact@v4 with: name: python-package-distributions - path: dist/ + path: backend/dist/ publish-to-pypi: name: Publish IMAS-IBEX distribution to PyPI diff --git a/backend/ibex/core/ibex_service.py b/backend/ibex/core/ibex_service.py index 1a4e337..91e1a39 100644 --- a/backend/ibex/core/ibex_service.py +++ b/backend/ibex/core/ibex_service.py @@ -135,7 +135,7 @@ def get_data(uri: str, downsampling_method: str | None, downsampled_size: int, r occurrence=uri_obj.occurrence, downsampling_method=downsampling_method, downsampled_size=downsampled_size, - range=range + range=range, ) diff --git a/backend/ibex/core/utils.py b/backend/ibex/core/utils.py index 04a7ce3..db53df1 100644 --- a/backend/ibex/core/utils.py +++ b/backend/ibex/core/utils.py @@ -116,19 +116,19 @@ class DownsamplingMethods(Enum): "name": "Min-Max", "description": "Selects the minimum and maximum value in each bin", "function": MinMaxDownsampler().downsample, - "validation" : (lambda target_size : target_size%2 == 0, "Min-Max downsampling target size must be even"), + "validation": (lambda target_size: target_size % 2 == 0, "Min-Max downsampling target size must be even"), } M4 = { "name": "M4", "description": "Selects the minimum, maximum, first, and last value in each bin", "function": M4Downsampler().downsample, - "validation": (lambda target_size: target_size%4 == 0, "M4 downsampling target size must be divisible by 4"), + "validation": (lambda target_size: target_size % 4 == 0, "M4 downsampling target size must be divisible by 4"), } LTTB = { "name": "LTTB", "description": "Implements the Largest Triangle Three Buckets (LTTB) algorithm", "function": LTTBDownsampler().downsample, - "validation": (lambda target_size: target_size>=3, "Minimum downsampling size for LTTB is 3"), + "validation": (lambda target_size: target_size >= 3, "Minimum downsampling size for LTTB is 3"), } MIN_MAX_LTTB = { "name": "Min-Max LTTB", @@ -146,13 +146,12 @@ def _missing_(cls, name): raise ValueError(f"Downsampling method: {name} is not recognised by IBEX backend") @classmethod - def validate_downsampling_target_size(cls, method : dict, target_size : int): - if "validation" in method.keys(): + def validate_downsampling_target_size(cls, method: dict, target_size: int): + if "validation" in method.keys(): if not method["validation"][0](target_size): raise InvalidParametersException(method["validation"][1]) - def downsample_data(data: List, target_size: int, method: str | None = None, x=None, single_x_axis=True): """ Downsamples list of values diff --git a/backend/ibex/data_source/imas_python_source.py b/backend/ibex/data_source/imas_python_source.py index 983375f..0471bee 100644 --- a/backend/ibex/data_source/imas_python_source.py +++ b/backend/ibex/data_source/imas_python_source.py @@ -246,7 +246,7 @@ def _get_raw_data(self, ids_obj: IDSBase, path_elements: List[IDSPath] | None): new_ids_obj = ids_obj[f"{path_node_name}[{path_index}]"] except AttributeError as e: raise NodeNotFoundException(e) - except IndexError as e: + except IndexError: message = f"Index out of range: {path_node_name} has no index {path_index}" raise NodeNotFoundException(message) return self._get_raw_data(new_ids_obj, path_elements[1:]) @@ -822,7 +822,6 @@ def get_plot_data( coordinate["coordinates"] = new_shape_factors_list return result - def _is_empty(self, seq): """Checks if list is essentially empty (contains only empty lists or empty strings)""" if isinstance(seq, (IDSNumericArray, IDSString0D, IDSString1D, IDSComplex0D, IDSFloat0D, IDSInt0D)): @@ -841,11 +840,14 @@ def _replace_empty_numbers(self, arr, replace_to=np.nan): if isinstance(x, list): self._replace_empty_numbers(x, replace_to) else: - try: if not x.has_value: arr[i] = replace_to # exception occurs for numpy values e.g. numpy.float64 except AttributeError: - if x == imas.ids_defs.EMPTY_FLOAT or x == imas.ids_defs.EMPTY_INT or x == imas.ids_defs.EMPTY_COMPLEX: + if ( + x == imas.ids_defs.EMPTY_FLOAT + or x == imas.ids_defs.EMPTY_INT + or x == imas.ids_defs.EMPTY_COMPLEX + ): arr[i] = replace_to diff --git a/backend/ibex/setup_logging.py b/backend/ibex/setup_logging.py index 6ae5df1..681e33e 100644 --- a/backend/ibex/setup_logging.py +++ b/backend/ibex/setup_logging.py @@ -15,7 +15,7 @@ class _PrettyFormatter(logging.Formatter): white = "[white]" reset = "[/]" - formatstr = "%(asctime)s %(levelname)-8s %(message)s " f"{light_grey}@%(filename)s:%(lineno)d{reset}" + formatstr = f"%(asctime)s %(levelname)-8s %(message)s {light_grey}@%(filename)s:%(lineno)d{reset}" time_format = "%H:%M:%S" FORMATS = { diff --git a/backend/tests/response_times.py b/backend/tests/response_times.py index 50f7d21..4648d9a 100644 --- a/backend/tests/response_times.py +++ b/backend/tests/response_times.py @@ -15,7 +15,7 @@ def wrap(*args, **kw): te = time.time() print(f"============= {f.__name__} =============") print(f" ARGS: {args}{kw}") - print(f" EXECUTION_TIME: {te-ts} sec") + print(f" EXECUTION_TIME: {te - ts} sec") print(f" RECEIVED ARRAY SHAPE: {result}") print(f" STATUS CODE: {status_code}") print("==========================") @@ -84,5 +84,5 @@ def field_value(uri): ts = time.time() field_value(f"{uri}{node_path.replace('[:]', slice)}") te = time.time() - print(f" {round(te-ts,2)}".ljust(7), end="") + print(f" {round(te - ts, 2)}".ljust(7), end="") print() diff --git a/backend/tests/test_error_codes.py b/backend/tests/test_error_codes.py index f09976a..e221d11 100644 --- a/backend/tests/test_error_codes.py +++ b/backend/tests/test_error_codes.py @@ -4,33 +4,33 @@ def test_non_existing_ids_node_info(): parameters = {"uri": "imas:hdf5?path=non_existing_path"} response = pytest.test_client.get("/ids_info/node_info", params=parameters) - assert ( - response.status_code == 404 - ), "node_info endpoint should return 404 when trying to open non existing pulsefile" + assert response.status_code == 404, ( + "node_info endpoint should return 404 when trying to open non existing pulsefile" + ) def test_non_existing_ids_field_value(): parameters = {"uri": "imas:hdf5?path=non_existing_path"} response = pytest.test_client.get("/data/field_value", params=parameters) - assert ( - response.status_code == 404 - ), "node_info endpoint should return 404 when trying to open non existing pulsefile" + assert response.status_code == 404, ( + "node_info endpoint should return 404 when trying to open non existing pulsefile" + ) def test_non_existing_node_ids_info(entry_path): parameters = {"uri": f"imas:hdf5?path={entry_path}#core_profiles/non_existing_node"} response = pytest.test_client.get("/ids_info/node_info", params=parameters) - assert ( - response.status_code == 404 - ), "node_info endpoint should return 404 when trying to open non existing node path" + assert response.status_code == 404, ( + "node_info endpoint should return 404 when trying to open non existing node path" + ) def test_non_existing_node_field_value(entry_path): parameters = {"uri": f"imas:hdf5?path={entry_path}#core_profiles/non_existing_node"} response = pytest.test_client.get("/data/field_value", params=parameters) - assert ( - response.status_code == 404 - ), "node_info endpoint should return 404 when trying to open non existing node path" + assert response.status_code == 404, ( + "node_info endpoint should return 404 when trying to open non existing node path" + ) def test_result_too_long(entry_path): @@ -56,6 +56,6 @@ def test_node_is_not_leaf_array_summary(entry_path): def test_node_is_not_array(entry_path): parameters = {"uri": f"imas:hdf5?path={entry_path}#core_profiles/ids_properties/version_put/access_layer"} response = pytest.test_client.get("/ids_info/array_summary", params=parameters) - assert ( - response.status_code == 462 - ), "array_summary endpoint should return 462 when trying to get summary of non array node" + assert response.status_code == 462, ( + "array_summary endpoint should return 462 when trying to get summary of non array node" + ) diff --git a/backend/tests/test_ids_info_endpoints.py b/backend/tests/test_ids_info_endpoints.py index 63dcfa6..75fdc78 100644 --- a/backend/tests/test_ids_info_endpoints.py +++ b/backend/tests/test_ids_info_endpoints.py @@ -78,13 +78,13 @@ def test_show_error_bars_option(entry_path): assert response.status_code == 200 for child in response.json()["children"]: - assert not any( - x in child["name"] for x in ["_error_upper", "_error_lower", "_error_index"] - ), f"Error bars filtering failed. Node {child['name']} should not be returned." + assert not any(x in child["name"] for x in ["_error_upper", "_error_lower", "_error_index"]), ( + f"Error bars filtering failed. Node {child['name']} should not be returned." + ) parameters = {"uri": f"imas:hdf5?path={entry_path}#core_profiles/vacuum_toroidal_field", "show_error_bars": True} response = pytest.test_client.get("/ids_info/node_info", params=parameters) assert response.status_code == 200 - assert "r0_error_upper" in [ - child["name"] for child in response.json()["children"] - ], "Error bars filtering failed. 'r0_error_upper' nodes was not returned, but it should be." + assert "r0_error_upper" in [child["name"] for child in response.json()["children"]], ( + "Error bars filtering failed. 'r0_error_upper' nodes was not returned, but it should be." + )