diff --git a/hvpy/api_groups/jpeg2000/get_jp2_header.py b/hvpy/api_groups/jpeg2000/get_jp2_header.py new file mode 100644 index 0000000..95492ab --- /dev/null +++ b/hvpy/api_groups/jpeg2000/get_jp2_header.py @@ -0,0 +1,29 @@ +from typing import Optional + +from hvpy.io import HvpyParameters, OutputType + + +class getJP2HeaderInputParameters(HvpyParameters): + """ + Handles the input parameters of the getJP2Header API. + + Attributes + ---------- + id : int + Unique JP2 image identifier. + callback : str, optional + Wrap the response object in a function call of your choosing. + + References + ---------- + * ``__ + """ + + id: int + callback: Optional[str] = None + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + return OutputType.STRING diff --git a/hvpy/api_groups/jpeg2000/get_jp2_image.py b/hvpy/api_groups/jpeg2000/get_jp2_image.py index 8e43b6f..7374614 100644 --- a/hvpy/api_groups/jpeg2000/get_jp2_image.py +++ b/hvpy/api_groups/jpeg2000/get_jp2_image.py @@ -3,6 +3,7 @@ from pydantic import Field, validator from hvpy.io import HvpyParameters, OutputType +from hvpy.utils import convert_date_to_isoformat class getJP2ImageInputParameters(HvpyParameters): @@ -31,13 +32,7 @@ class getJP2ImageInputParameters(HvpyParameters): sourceId: int jpip: bool = False Json: bool = Field(False, alias="json") - - @validator("date") - def convert_date_to_isoformat(cls, v) -> str: - """ - Converts the date from a datetime object to a string in the ISO format. - """ - return v.isoformat() + "Z" + _date_validator = validator("date", allow_reuse=True)(convert_date_to_isoformat) def get_output_type(self) -> OutputType: """ diff --git a/hvpy/api_groups/jpeg2000/get_jpx.py b/hvpy/api_groups/jpeg2000/get_jpx.py new file mode 100644 index 0000000..edff57c --- /dev/null +++ b/hvpy/api_groups/jpeg2000/get_jpx.py @@ -0,0 +1,54 @@ +from typing import Optional +from datetime import datetime + +from pydantic import validator + +from hvpy.io import HvpyParameters, OutputType +from hvpy.utils import convert_date_to_isoformat + + +class getJPXInputParameters(HvpyParameters): + """ + Handles the input parameters of the getJPX API. + + Attributes + ---------- + startTime : datetime + Date/Time for the beginning of the JPX movie data. + endTime : datetime + Date/Time for the end of the JPX movie data. + sourceId : int + Unique image datasource identifier. + linked : bool, optional + Generate a linked JPX file containing image pointers instead of data for each individual frame in the series. + verbose : bool, optional + If set to true, the JSON response will include timestamps for each frame in the resulting movie and any warning messages associated with the request, in addition to the JPX movie file URI. + jpip : bool, optional + Optionally return a JPIP URI string instead of the binary data of the movie itself, or instead of an HTTP URI in the JSON response (if verbose is set to true). + cadence : int, optional + The desired amount of time (in seconds) between each frame in the movie. + + References + ---------- + * ``__ + """ + + startTime: datetime + endTime: datetime + sourceId: int + linked: bool = True + verbose: bool = False + jpip: bool = False + cadence: Optional[int] = None + _date_validator = validator("startTime", "endTime", allow_reuse=True)(convert_date_to_isoformat) + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + if not self.jpip and not self.verbose: + return OutputType.RAW + elif self.jpip and not self.verbose: + return OutputType.STRING + else: + return OutputType.JSON diff --git a/hvpy/api_groups/jpeg2000/get_jpx_closest_to_mid_point.py b/hvpy/api_groups/jpeg2000/get_jpx_closest_to_mid_point.py new file mode 100644 index 0000000..fc8d891 --- /dev/null +++ b/hvpy/api_groups/jpeg2000/get_jpx_closest_to_mid_point.py @@ -0,0 +1,51 @@ +from typing import List +from datetime import datetime + +from pydantic import validator + +from hvpy.io import HvpyParameters, OutputType +from hvpy.utils import convert_date_to_unix + + +class getJPXClosestToMidPointInputParameters(HvpyParameters): + """ + Handles the input parameters of the getJPXClosestToMidPoint API. + + Attributes + ---------- + startTimes : datetime + Comma separated timestamps for the beginning of the JPX movie data. + endTimes : datetime + Comma separated timestamps for the end of the JPX movie data. + sourceId : int + Unique image datasource identifier. + linked : bool, optional + Generate a linked JPX file containing image pointers instead of data for each individual frame in the series. + verbose : bool, optional + If set to true, the JSON response will include timestamps for each frame in the resulting movie and any warning messages associated with the request, in addition to the JPX movie file URI. + jpip : bool, optional + Optionally return a JPIP URI string instead of the binary data of the movie itself, or instead of an HTTP URI in the JSON response (if verbose is set to true). + + References + ---------- + * ``__ + """ + + startTimes: List[datetime] + endTimes: List[datetime] + sourceId: int + linked: bool = True + verbose: bool = False + jpip: bool = False + _date_validator = validator("startTimes", "endTimes", allow_reuse=True)(convert_date_to_unix) + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + if not self.jpip and not self.verbose: + return OutputType.RAW + elif self.jpip and not self.verbose: + return OutputType.STRING + else: + return OutputType.JSON diff --git a/hvpy/api_groups/jpeg2000/get_status.py b/hvpy/api_groups/jpeg2000/get_status.py new file mode 100644 index 0000000..5de5ff2 --- /dev/null +++ b/hvpy/api_groups/jpeg2000/get_status.py @@ -0,0 +1,18 @@ +from hvpy.io import HvpyParameters, OutputType + + +class getStatusInputParameters(HvpyParameters): + """ + Returns information about how far behind the latest available JPEG2000 + images. + + References + ---------- + * ``__ + """ + + def get_output_type(self) -> OutputType: + """ + Returns the output type of the API call. + """ + return OutputType.JSON diff --git a/hvpy/api_groups/jpeg2000/tests/test_get_jp2_header.py b/hvpy/api_groups/jpeg2000/tests/test_get_jp2_header.py new file mode 100644 index 0000000..2d7c3c4 --- /dev/null +++ b/hvpy/api_groups/jpeg2000/tests/test_get_jp2_header.py @@ -0,0 +1,28 @@ +import pytest +from pydantic import ValidationError + +from hvpy.api_groups.jpeg2000.get_jp2_header import getJP2HeaderInputParameters +from hvpy.core import execute_api_call + + +def test_getJP2HeaderInputParameters(): + params = getJP2HeaderInputParameters(id=9838343) + response = execute_api_call(input_parameters=params) + assert isinstance(response, str) + assert response.startswith("") + + params = getJP2HeaderInputParameters(id=9838343, callback="my_callback") + response = execute_api_call(input_parameters=params) + assert isinstance(response, str) + assert response.startswith("my_callback(") + + +def test_error_handling(): + with pytest.raises(ValidationError, match="getJP2HeaderInputParameters\nid\n field required"): + getJP2HeaderInputParameters(callback="my_callback") + + +def test_url_property(): + params = getJP2HeaderInputParameters(id=9838343) + assert params.url == "https://api.helioviewer.org/v2/getJP2Header/" diff --git a/hvpy/api_groups/jpeg2000/tests/test_get_jp2_image.py b/hvpy/api_groups/jpeg2000/tests/test_get_jp2_image.py index a17fbb1..c2a0ce4 100644 --- a/hvpy/api_groups/jpeg2000/tests/test_get_jp2_image.py +++ b/hvpy/api_groups/jpeg2000/tests/test_get_jp2_image.py @@ -40,7 +40,6 @@ def test_error_handling(): def test_url_property(): - date_obj = datetime(2022, 1, 1, 23, 59, 59) - params = {"date": date_obj, "sourceId": 14, "jpip": True, "json": True} + params = {"date": datetime(2022, 1, 1, 23, 59, 59), "sourceId": 14, "jpip": True, "json": True} params = getJP2ImageInputParameters(**params) assert params.url == "https://api.helioviewer.org/v2/getJP2Image/" diff --git a/hvpy/api_groups/jpeg2000/tests/test_get_jpx.py b/hvpy/api_groups/jpeg2000/tests/test_get_jpx.py new file mode 100644 index 0000000..54eff12 --- /dev/null +++ b/hvpy/api_groups/jpeg2000/tests/test_get_jpx.py @@ -0,0 +1,82 @@ +from datetime import datetime + +import pytest +from pydantic import ValidationError + +from hvpy.api_groups.jpeg2000.get_jpx import getJPXInputParameters +from hvpy.core import execute_api_call + + +def test_raw_response(): + params = getJPXInputParameters( + startTime=datetime(2014, 1, 1, 0, 0, 0), + endTime=datetime(2014, 1, 1, 0, 45, 0), + sourceId=14, + linked=False, + verbose=False, + jpip=False, + cadence=None, + ) + response = execute_api_call(params) + assert isinstance(response, bytes) + + +def test_str_response(): + params = getJPXInputParameters( + startTime=datetime(2014, 1, 1, 0, 0, 0), + endTime=datetime(2014, 1, 1, 0, 45, 0), + sourceId=14, + linked=False, + verbose=False, + jpip=True, + cadence=None, + ) + response = execute_api_call(params) + assert isinstance(response, str) + assert response.startswith("jpip://") + + +def test_json_response(): + params = getJPXInputParameters( + startTime=datetime(2014, 1, 1, 0, 0, 0), + endTime=datetime(2014, 1, 1, 0, 45, 0), + sourceId=14, + linked=False, + verbose=True, + jpip=True, + cadence=None, + ) + response = execute_api_call(params) + assert isinstance(response, dict) + assert response["uri"].startswith("jpip://") + + params = getJPXInputParameters( + startTime=datetime(2014, 1, 1, 0, 0, 0), + endTime=datetime(2014, 1, 1, 0, 45, 0), + sourceId=14, + linked=False, + verbose=True, + jpip=False, + cadence=None, + ) + response = execute_api_call(params) + assert isinstance(response, dict) + assert response["uri"].startswith("https://") + + +def test_error_handling(): + with pytest.raises(ValidationError, match="getJPXInputParameters\nstartTime\n field required"): + getJPXInputParameters(endTime=datetime(2014, 1, 1, 0, 45, 0), sourceId=14) + + with pytest.raises(ValidationError, match="getJPXInputParameters\nendTime\n field required"): + getJPXInputParameters(startTime=datetime(2014, 1, 1, 0, 0, 0), sourceId=14) + + with pytest.raises(ValidationError, match="getJPXInputParameters\nsourceId\n field required"): + getJPXInputParameters(startTime=datetime(2014, 1, 1, 0, 0, 0), endTime=datetime(2014, 1, 1, 0, 45, 0)) + + +def test_url_property(): + params = getJPXInputParameters( + startTime=datetime(2014, 1, 1, 0, 0, 0), endTime=datetime(2014, 1, 1, 0, 45, 0), sourceId=14 + ) + assert params.url == "https://api.helioviewer.org/v2/getJPX/" diff --git a/hvpy/api_groups/jpeg2000/tests/test_get_jpx_closest_to_mid_point.py b/hvpy/api_groups/jpeg2000/tests/test_get_jpx_closest_to_mid_point.py new file mode 100644 index 0000000..f585fdf --- /dev/null +++ b/hvpy/api_groups/jpeg2000/tests/test_get_jpx_closest_to_mid_point.py @@ -0,0 +1,59 @@ +from datetime import datetime + +import pytest +from pydantic import ValidationError + +from hvpy.api_groups.jpeg2000.get_jpx_closest_to_mid_point import getJPXClosestToMidPointInputParameters +from hvpy.core import execute_api_call + +startTimes = [datetime(2014, 1, 1, 0, 0, 0), datetime(2014, 1, 1, 2, 3, 3), datetime(2014, 1, 1, 4, 5, 5)] +endTimes = [datetime(2014, 1, 1, 0, 45, 0), datetime(2014, 1, 1, 2, 33, 3), datetime(2014, 1, 1, 4, 54, 5)] + + +def test_raw_response(): + params = getJPXClosestToMidPointInputParameters( + startTimes=startTimes, endTimes=endTimes, sourceId=14, linked=False, verbose=False, jpip=False + ) + response = execute_api_call(input_parameters=params) + assert isinstance(response, bytes) + + +def test_str_response(): + params = getJPXClosestToMidPointInputParameters( + startTimes=startTimes, endTimes=endTimes, sourceId=14, linked=False, verbose=False, jpip=True + ) + response = execute_api_call(input_parameters=params) + assert isinstance(response, str) + assert response.startswith("jpip://") + + +def test_json_response(): + params = getJPXClosestToMidPointInputParameters( + startTimes=startTimes, endTimes=endTimes, sourceId=14, linked=False, verbose=True, jpip=True + ) + response = execute_api_call(input_parameters=params) + assert isinstance(response, dict) + assert response["uri"].startswith("jpip://") + + params = getJPXClosestToMidPointInputParameters( + startTimes=startTimes, endTimes=endTimes, sourceId=14, linked=False, verbose=True, jpip=False + ) + response = execute_api_call(input_parameters=params) + assert isinstance(response, dict) + assert response["uri"].startswith("https://") + + +def test_error_handling(): + with pytest.raises(ValidationError, match="getJPXClosestToMidPointInputParameters\nstartTimes\n field required"): + getJPXClosestToMidPointInputParameters(endTimes=endTimes, sourceId=14) + + with pytest.raises(ValidationError, match="getJPXClosestToMidPointInputParameters\nendTimes\n field required"): + getJPXClosestToMidPointInputParameters(startTimes=startTimes, sourceId=14) + + with pytest.raises(ValidationError, match="getJPXClosestToMidPointInputParameters\nsourceId\n field required"): + getJPXClosestToMidPointInputParameters(startTimes=startTimes, endTimes=endTimes) + + +def test_url_property(): + params = getJPXClosestToMidPointInputParameters(startTimes=startTimes, endTimes=endTimes, sourceId=14) + assert params.url == "https://api.helioviewer.org/v2/getJPXClosestToMidPoint/" diff --git a/hvpy/api_groups/jpeg2000/tests/test_get_status.py b/hvpy/api_groups/jpeg2000/tests/test_get_status.py new file mode 100644 index 0000000..3a35aee --- /dev/null +++ b/hvpy/api_groups/jpeg2000/tests/test_get_status.py @@ -0,0 +1,13 @@ +from hvpy.api_groups.jpeg2000.get_status import getStatusInputParameters +from hvpy.core import execute_api_call + + +def test_getStatusInputParameters(): + params = getStatusInputParameters() + response = execute_api_call(input_parameters=params) + assert isinstance(response, dict) + + +def test_url_property(): + params = getStatusInputParameters() + assert params.url == "https://api.helioviewer.org/v2/getStatus/" diff --git a/hvpy/io.py b/hvpy/io.py index e87af04..6756f96 100644 --- a/hvpy/io.py +++ b/hvpy/io.py @@ -1,7 +1,7 @@ from enum import Enum, auto from typing import Any, Dict -from pydantic.main import BaseModel +from pydantic import BaseModel __all__ = ["HvpyParameters", "OutputType"] diff --git a/hvpy/utils.py b/hvpy/utils.py index 4c8f64c..c6e9d27 100644 --- a/hvpy/utils.py +++ b/hvpy/utils.py @@ -1,6 +1,7 @@ from typing import Any, Callable +from datetime import datetime -__all__ = ["add_shared_docstring"] +__all__ = ["add_shared_docstring", "convert_date_to_isoformat", "convert_date_to_unix"] def add_shared_docstring(input_class) -> Callable[[Any], Any]: @@ -12,3 +13,18 @@ def decorator(func): return func return decorator + + +def convert_date_to_isoformat(v: datetime) -> str: + """ + Converts the date from a datetime object to a string in the ISO format. + """ + return v.isoformat() + "Z" + + +def convert_date_to_unix(v: list) -> str: + """ + Converts a list of datetimes to Unix timestamps format separated with + commas. + """ + return ",".join([str(int(datetime.timestamp(d))) for d in v])