diff --git a/docs/user-guide/tutorials/Drifter_data_tutorial.ipynb b/docs/user-guide/tutorials/Drifter_data_tutorial.ipynb index 41c62bfa..c2d9424a 100755 --- a/docs/user-guide/tutorials/Drifter_data_tutorial.ipynb +++ b/docs/user-guide/tutorials/Drifter_data_tutorial.ipynb @@ -17,7 +17,7 @@ "metadata": {}, "outputs": [], "source": [ - "from virtualship import Location, Spacetime\n", + "from virtualship.models import Location, Spacetime\n", "from virtualship.instruments.drifter import Drifter, simulate_drifters\n", "from virtualship.expedition.input_data import InputData\n", "from pathlib import Path\n", diff --git a/pyproject.toml b/pyproject.toml index c15a19cd..34431572 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -95,6 +95,7 @@ select = [ "ICN", # import conventions "RUF", # ruff "ISC001", # single-line-implicit-string-concatenation + "TID", # flake8-tidy-imports ] ignore = [ # line too long (82 > 79 characters) diff --git a/src/virtualship/__init__.py b/src/virtualship/__init__.py index 877fe4e1..596b9c2c 100644 --- a/src/virtualship/__init__.py +++ b/src/virtualship/__init__.py @@ -2,9 +2,6 @@ from importlib.metadata import version as _version -from .location import Location -from .spacetime import Spacetime - try: __version__ = _version("virtualship") except Exception: @@ -12,7 +9,5 @@ __version__ = "unknown" __all__ = [ - "Location", - "Spacetime", "__version__", ] diff --git a/src/virtualship/cli/_creds.py b/src/virtualship/cli/_creds.py index cee1c69f..9f1d2435 100644 --- a/src/virtualship/cli/_creds.py +++ b/src/virtualship/cli/_creds.py @@ -6,13 +6,9 @@ import pydantic import yaml -CREDENTIALS_FILE = "credentials.yaml" - +from virtualship.errors import CredentialFileError -class CredentialFileError(Exception): - """Exception raised for errors in the input file format.""" - - pass +CREDENTIALS_FILE = "credentials.yaml" class Credentials(pydantic.BaseModel): diff --git a/src/virtualship/cli/_fetch.py b/src/virtualship/cli/_fetch.py index f07c5b92..df66cd66 100644 --- a/src/virtualship/cli/_fetch.py +++ b/src/virtualship/cli/_fetch.py @@ -8,6 +8,7 @@ from pydantic import BaseModel +from virtualship.errors import IncompleteDownloadError from virtualship.utils import ( _dump_yaml, _generic_load_yaml, @@ -16,7 +17,7 @@ ) if TYPE_CHECKING: - from virtualship.expedition.space_time_region import SpaceTimeRegion + from virtualship.models import SpaceTimeRegion import click import copernicusmarine @@ -38,7 +39,7 @@ def _fetch(path: str | Path, username: str | None, password: str | None) -> None be provided on prompt, via command line arguments, or via a YAML config file. Run `virtualship fetch` on an expedition for more info. """ - from virtualship.expedition.ship_config import InstrumentType + from virtualship.models import InstrumentType if sum([username is None, password is None]) == 1: raise ValueError("Both username and password must be provided when using CLI.") @@ -329,12 +330,6 @@ def hash_to_filename(hash: str) -> str: return f"{datetime.now().strftime('%Y%m%d_%H%M%S')}_{hash}" -class IncompleteDownloadError(Exception): - """Exception raised for incomplete downloads.""" - - pass - - class DownloadMetadata(BaseModel): """Metadata for a data download.""" diff --git a/src/virtualship/errors.py b/src/virtualship/errors.py new file mode 100644 index 00000000..838a62a8 --- /dev/null +++ b/src/virtualship/errors.py @@ -0,0 +1,28 @@ +class CredentialFileError(Exception): + """Exception raised for errors in the input file format.""" + + pass + + +class IncompleteDownloadError(Exception): + """Exception raised for incomplete downloads.""" + + pass + + +class CheckpointError(RuntimeError): + """An error in the checkpoint.""" + + pass + + +class ScheduleError(RuntimeError): + """An error in the schedule.""" + + pass + + +class ConfigError(RuntimeError): + """An error in the config.""" + + pass diff --git a/src/virtualship/expedition/__init__.py b/src/virtualship/expedition/__init__.py index 65b7cf11..43d24844 100644 --- a/src/virtualship/expedition/__init__.py +++ b/src/virtualship/expedition/__init__.py @@ -2,31 +2,8 @@ from .do_expedition import do_expedition from .input_data import InputData -from .schedule import Schedule, Waypoint -from .ship_config import ( - ADCPConfig, - ArgoFloatConfig, - CTD_BGCConfig, - CTDConfig, - DrifterConfig, - ShipConfig, - ShipUnderwaterSTConfig, -) -from .space_time_region import SpaceTimeRegion __all__ = [ - "ADCPConfig", - "ArgoFloatConfig", - "CTDConfig", - "CTD_BGCConfig", - "DrifterConfig", "InputData", - "InstrumentType", - "Schedule", - "ShipConfig", - "ShipUnderwaterSTConfig", - "SpaceTimeRegion", - "Waypoint", "do_expedition", - "instruments", ] diff --git a/src/virtualship/expedition/checkpoint.py b/src/virtualship/expedition/checkpoint.py index be6079ef..6daf1a9b 100644 --- a/src/virtualship/expedition/checkpoint.py +++ b/src/virtualship/expedition/checkpoint.py @@ -7,8 +7,8 @@ import pydantic import yaml -from .schedule import Schedule -from .ship_config import InstrumentType +from virtualship.errors import CheckpointError +from virtualship.models import InstrumentType, Schedule class _YamlDumper(yaml.SafeDumper): @@ -71,9 +71,3 @@ def verify(self, schedule: Schedule) -> None: raise CheckpointError( "Past waypoints in schedule have been changed! Restore past schedule and only change future waypoints." ) - - -class CheckpointError(RuntimeError): - """An error in the checkpoint.""" - - pass diff --git a/src/virtualship/expedition/do_expedition.py b/src/virtualship/expedition/do_expedition.py index 6d7d236f..84150de8 100644 --- a/src/virtualship/expedition/do_expedition.py +++ b/src/virtualship/expedition/do_expedition.py @@ -7,6 +7,7 @@ import pyproj from virtualship.cli._fetch import get_existing_download, get_space_time_region_hash +from virtualship.models import Schedule, ShipConfig from virtualship.utils import ( CHECKPOINT, _get_schedule, @@ -16,8 +17,6 @@ from .checkpoint import Checkpoint from .expedition_cost import expedition_cost from .input_data import InputData -from .schedule import Schedule -from .ship_config import ShipConfig from .simulate_measurements import simulate_measurements from .simulate_schedule import ScheduleProblem, simulate_schedule diff --git a/src/virtualship/expedition/simulate_measurements.py b/src/virtualship/expedition/simulate_measurements.py index 536d2a93..31610332 100644 --- a/src/virtualship/expedition/simulate_measurements.py +++ b/src/virtualship/expedition/simulate_measurements.py @@ -6,14 +6,15 @@ from pathlib import Path from typing import TYPE_CHECKING -from ..instruments.adcp import simulate_adcp -from ..instruments.argo_float import simulate_argo_floats -from ..instruments.ctd import simulate_ctd -from ..instruments.ctd_bgc import simulate_ctd_bgc -from ..instruments.drifter import simulate_drifters -from ..instruments.ship_underwater_st import simulate_ship_underwater_st -from ..instruments.xbt import simulate_xbt -from .ship_config import ShipConfig +from virtualship.instruments.adcp import simulate_adcp +from virtualship.instruments.argo_float import simulate_argo_floats +from virtualship.instruments.ctd import simulate_ctd +from virtualship.instruments.ctd_bgc import simulate_ctd_bgc +from virtualship.instruments.drifter import simulate_drifters +from virtualship.instruments.ship_underwater_st import simulate_ship_underwater_st +from virtualship.instruments.xbt import simulate_xbt +from virtualship.models import ShipConfig + from .simulate_schedule import MeasurementsToSimulate if TYPE_CHECKING: diff --git a/src/virtualship/expedition/simulate_schedule.py b/src/virtualship/expedition/simulate_schedule.py index 596d16a2..95fa2f5f 100644 --- a/src/virtualship/expedition/simulate_schedule.py +++ b/src/virtualship/expedition/simulate_schedule.py @@ -7,15 +7,19 @@ import pyproj -from ..instruments.argo_float import ArgoFloat -from ..instruments.ctd import CTD -from ..instruments.ctd_bgc import CTD_BGC -from ..instruments.drifter import Drifter -from ..instruments.xbt import XBT -from ..location import Location -from ..spacetime import Spacetime -from .schedule import Schedule, Waypoint -from .ship_config import InstrumentType, ShipConfig +from virtualship.instruments.argo_float import ArgoFloat +from virtualship.instruments.ctd import CTD +from virtualship.instruments.ctd_bgc import CTD_BGC +from virtualship.instruments.drifter import Drifter +from virtualship.instruments.xbt import XBT +from virtualship.models import ( + InstrumentType, + Location, + Schedule, + ShipConfig, + Spacetime, + Waypoint, +) @dataclass diff --git a/src/virtualship/instruments/adcp.py b/src/virtualship/instruments/adcp.py index 5563bdd2..af2c285e 100644 --- a/src/virtualship/instruments/adcp.py +++ b/src/virtualship/instruments/adcp.py @@ -5,7 +5,7 @@ import numpy as np from parcels import FieldSet, ParticleSet, ScipyParticle, Variable -from ..spacetime import Spacetime +from virtualship.models import Spacetime # we specifically use ScipyParticle because we have many small calls to execute # there is some overhead with JITParticle and this ends up being significantly faster diff --git a/src/virtualship/instruments/argo_float.py b/src/virtualship/instruments/argo_float.py index 2091098e..d0976367 100644 --- a/src/virtualship/instruments/argo_float.py +++ b/src/virtualship/instruments/argo_float.py @@ -15,7 +15,7 @@ Variable, ) -from ..spacetime import Spacetime +from virtualship.models import Spacetime @dataclass diff --git a/src/virtualship/instruments/ctd.py b/src/virtualship/instruments/ctd.py index 6f76b408..41185007 100644 --- a/src/virtualship/instruments/ctd.py +++ b/src/virtualship/instruments/ctd.py @@ -7,7 +7,7 @@ import numpy as np from parcels import FieldSet, JITParticle, ParticleSet, Variable -from ..spacetime import Spacetime +from virtualship.models import Spacetime @dataclass diff --git a/src/virtualship/instruments/ctd_bgc.py b/src/virtualship/instruments/ctd_bgc.py index cb218e3a..acd4df61 100644 --- a/src/virtualship/instruments/ctd_bgc.py +++ b/src/virtualship/instruments/ctd_bgc.py @@ -7,7 +7,7 @@ import numpy as np from parcels import FieldSet, JITParticle, ParticleSet, Variable -from ..spacetime import Spacetime +from virtualship.models import Spacetime @dataclass diff --git a/src/virtualship/instruments/drifter.py b/src/virtualship/instruments/drifter.py index 2fd4180b..5aef240f 100644 --- a/src/virtualship/instruments/drifter.py +++ b/src/virtualship/instruments/drifter.py @@ -7,7 +7,7 @@ import numpy as np from parcels import AdvectionRK4, FieldSet, JITParticle, ParticleSet, Variable -from ..spacetime import Spacetime +from virtualship.models import Spacetime @dataclass diff --git a/src/virtualship/instruments/ship_underwater_st.py b/src/virtualship/instruments/ship_underwater_st.py index 407055ad..7b08ad4b 100644 --- a/src/virtualship/instruments/ship_underwater_st.py +++ b/src/virtualship/instruments/ship_underwater_st.py @@ -5,7 +5,7 @@ import numpy as np from parcels import FieldSet, ParticleSet, ScipyParticle, Variable -from ..spacetime import Spacetime +from virtualship.models import Spacetime # we specifically use ScipyParticle because we have many small calls to execute # there is some overhead with JITParticle and this ends up being significantly faster diff --git a/src/virtualship/instruments/xbt.py b/src/virtualship/instruments/xbt.py index 36a28471..6d75be8c 100644 --- a/src/virtualship/instruments/xbt.py +++ b/src/virtualship/instruments/xbt.py @@ -7,7 +7,7 @@ import numpy as np from parcels import FieldSet, JITParticle, ParticleSet, Variable -from ..spacetime import Spacetime +from virtualship.models import Spacetime @dataclass diff --git a/src/virtualship/models/__init__.py b/src/virtualship/models/__init__.py new file mode 100644 index 00000000..48106056 --- /dev/null +++ b/src/virtualship/models/__init__.py @@ -0,0 +1,42 @@ +"""Pydantic models and data classes used to configure virtualship (i.e., in the configuration files or settings).""" + +from .location import Location +from .schedule import Schedule, Waypoint +from .ship_config import ( + ADCPConfig, + ArgoFloatConfig, + CTD_BGCConfig, + CTDConfig, + DrifterConfig, + InstrumentType, + ShipConfig, + ShipUnderwaterSTConfig, + XBTConfig, +) +from .space_time_region import ( + SpaceTimeRegion, + SpatialRange, + TimeRange, +) +from .spacetime import ( + Spacetime, +) + +__all__ = [ # noqa: RUF022 + "Location", + "Schedule", + "Waypoint", + "InstrumentType", + "ArgoFloatConfig", + "ADCPConfig", + "CTDConfig", + "CTD_BGCConfig", + "ShipUnderwaterSTConfig", + "DrifterConfig", + "XBTConfig", + "ShipConfig", + "SpatialRange", + "TimeRange", + "SpaceTimeRegion", + "Spacetime", +] diff --git a/src/virtualship/location.py b/src/virtualship/models/location.py similarity index 100% rename from src/virtualship/location.py rename to src/virtualship/models/location.py diff --git a/src/virtualship/expedition/schedule.py b/src/virtualship/models/schedule.py similarity index 97% rename from src/virtualship/expedition/schedule.py rename to src/virtualship/models/schedule.py index 4ecd5e7c..c29cd4c9 100644 --- a/src/virtualship/expedition/schedule.py +++ b/src/virtualship/models/schedule.py @@ -10,14 +10,18 @@ import pydantic import pyproj import yaml -from parcels import FieldSet -from ..location import Location +from virtualship.errors import ScheduleError + +from .location import Location from .ship_config import InstrumentType from .space_time_region import SpaceTimeRegion if TYPE_CHECKING: - from .input_data import InputData + from parcels import FieldSet + + from virtualship.expedition.input_data import InputData + projection: pyproj.Geod = pyproj.Geod(ellps="WGS84") @@ -212,12 +216,6 @@ def verify( time = wp_next.time -class ScheduleError(RuntimeError): - """An error in the schedule.""" - - pass - - def _is_on_land_zero_uv(fieldset: FieldSet, waypoint: Waypoint) -> bool: """ Check if waypoint is on land by assuming zero velocity means land. diff --git a/src/virtualship/expedition/ship_config.py b/src/virtualship/models/ship_config.py similarity index 99% rename from src/virtualship/expedition/ship_config.py rename to src/virtualship/models/ship_config.py index c0814f5b..be3ee30d 100644 --- a/src/virtualship/expedition/ship_config.py +++ b/src/virtualship/models/ship_config.py @@ -10,6 +10,7 @@ import pydantic import yaml +from virtualship.errors import ConfigError from virtualship.utils import _validate_numeric_mins_to_timedelta if TYPE_CHECKING: @@ -317,9 +318,3 @@ def verify(self, schedule: Schedule) -> None: raise ConfigError( "Planning has a waypoint with XBT instrument, but configuration does not configure XBT." ) - - -class ConfigError(RuntimeError): - """An error in the config.""" - - pass diff --git a/src/virtualship/expedition/space_time_region.py b/src/virtualship/models/space_time_region.py similarity index 100% rename from src/virtualship/expedition/space_time_region.py rename to src/virtualship/models/space_time_region.py diff --git a/src/virtualship/spacetime.py b/src/virtualship/models/spacetime.py similarity index 100% rename from src/virtualship/spacetime.py rename to src/virtualship/models/spacetime.py diff --git a/src/virtualship/utils.py b/src/virtualship/utils.py index 6dbbb49c..c494df96 100644 --- a/src/virtualship/utils.py +++ b/src/virtualship/utils.py @@ -9,8 +9,7 @@ from typing import TYPE_CHECKING, TextIO if TYPE_CHECKING: - from virtualship.expedition.schedule import Schedule - from virtualship.expedition.ship_config import ShipConfig + from virtualship.models import Schedule, ShipConfig import pandas as pd import yaml @@ -138,13 +137,14 @@ def mfp_to_yaml(coordinates_file_path: str, yaml_output_path: str): # noqa: D41 4. returns the yaml information. """ - # Importing Schedule and related models from expedition module - from virtualship.expedition.schedule import Location, Schedule, Waypoint - from virtualship.expedition.ship_config import InstrumentType - from virtualship.expedition.space_time_region import ( + from virtualship.models import ( + InstrumentType, + Location, + Schedule, SpaceTimeRegion, SpatialRange, TimeRange, + Waypoint, ) # Read data from file @@ -228,7 +228,7 @@ def _validate_numeric_mins_to_timedelta(value: int | float | timedelta) -> timed def _get_schedule(expedition_dir: Path) -> Schedule: """Load Schedule object from yaml config file in `expedition_dir`.""" - from virtualship.expedition.schedule import Schedule + from virtualship.models import Schedule file_path = expedition_dir.joinpath(SCHEDULE) try: @@ -238,7 +238,7 @@ def _get_schedule(expedition_dir: Path) -> Schedule: def _get_ship_config(expedition_dir: Path) -> ShipConfig: - from virtualship.expedition.ship_config import ShipConfig + from virtualship.models import ShipConfig file_path = expedition_dir.joinpath(SHIP_CONFIG) try: diff --git a/tests/cli/test_fetch.py b/tests/cli/test_fetch.py index 3102ca8b..856b72f6 100644 --- a/tests/cli/test_fetch.py +++ b/tests/cli/test_fetch.py @@ -16,8 +16,7 @@ hash_model, hash_to_filename, ) -from virtualship.expedition.schedule import Schedule -from virtualship.expedition.ship_config import ShipConfig +from virtualship.models import Schedule, ShipConfig from virtualship.utils import get_example_config, get_example_schedule diff --git a/tests/expedition/test_schedule.py b/tests/expedition/test_schedule.py index eabcbd9a..d45900e0 100644 --- a/tests/expedition/test_schedule.py +++ b/tests/expedition/test_schedule.py @@ -4,9 +4,9 @@ import pyproj import pytest -from virtualship import Location +from virtualship.errors import ScheduleError from virtualship.expedition.do_expedition import _load_input_data -from virtualship.expedition.schedule import Schedule, ScheduleError, Waypoint +from virtualship.models import Location, Schedule, Waypoint from virtualship.utils import _get_ship_config projection = pyproj.Geod(ellps="WGS84") diff --git a/tests/expedition/test_ship_config.py b/tests/expedition/test_ship_config.py index 920058d2..6444e985 100644 --- a/tests/expedition/test_ship_config.py +++ b/tests/expedition/test_ship_config.py @@ -2,8 +2,8 @@ import pytest -from virtualship.expedition.schedule import Schedule -from virtualship.expedition.ship_config import ConfigError, ShipConfig +from virtualship.errors import ConfigError +from virtualship.models import Schedule, ShipConfig from virtualship.utils import get_example_config, get_example_schedule expedition_dir = Path("expedition_dir") diff --git a/tests/expedition/test_simulate_schedule.py b/tests/expedition/test_simulate_schedule.py index 8c42097b..9eecd73d 100644 --- a/tests/expedition/test_simulate_schedule.py +++ b/tests/expedition/test_simulate_schedule.py @@ -2,13 +2,12 @@ import pyproj -from virtualship import Location -from virtualship.expedition import Schedule, ShipConfig, Waypoint from virtualship.expedition.simulate_schedule import ( ScheduleOk, ScheduleProblem, simulate_schedule, ) +from virtualship.models import Location, Schedule, ShipConfig, Waypoint def test_simulate_schedule_feasible() -> None: diff --git a/tests/instruments/test_adcp.py b/tests/instruments/test_adcp.py index f32014c8..569f15a1 100644 --- a/tests/instruments/test_adcp.py +++ b/tests/instruments/test_adcp.py @@ -6,8 +6,8 @@ import xarray as xr from parcels import FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.adcp import simulate_adcp +from virtualship.models import Location, Spacetime def test_simulate_adcp(tmpdir) -> None: diff --git a/tests/instruments/test_argo_float.py b/tests/instruments/test_argo_float.py index 31aafe53..3eda53ae 100644 --- a/tests/instruments/test_argo_float.py +++ b/tests/instruments/test_argo_float.py @@ -6,8 +6,8 @@ import xarray as xr from parcels import FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.argo_float import ArgoFloat, simulate_argo_floats +from virtualship.models import Location, Spacetime def test_simulate_argo_floats(tmpdir) -> None: diff --git a/tests/instruments/test_ctd.py b/tests/instruments/test_ctd.py index f1fc26a6..14e0a276 100644 --- a/tests/instruments/test_ctd.py +++ b/tests/instruments/test_ctd.py @@ -11,8 +11,8 @@ import xarray as xr from parcels import Field, FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.ctd import CTD, simulate_ctd +from virtualship.models import Location, Spacetime def test_simulate_ctds(tmpdir) -> None: diff --git a/tests/instruments/test_ctd_bgc.py b/tests/instruments/test_ctd_bgc.py index 8083c580..f26e34b1 100644 --- a/tests/instruments/test_ctd_bgc.py +++ b/tests/instruments/test_ctd_bgc.py @@ -11,8 +11,8 @@ import xarray as xr from parcels import Field, FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.ctd_bgc import CTD_BGC, simulate_ctd_bgc +from virtualship.models import Location, Spacetime def test_simulate_ctd_bgcs(tmpdir) -> None: diff --git a/tests/instruments/test_drifter.py b/tests/instruments/test_drifter.py index c62b5d60..ae230a87 100644 --- a/tests/instruments/test_drifter.py +++ b/tests/instruments/test_drifter.py @@ -6,8 +6,8 @@ import xarray as xr from parcels import FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.drifter import Drifter, simulate_drifters +from virtualship.models import Location, Spacetime def test_simulate_drifters(tmpdir) -> None: diff --git a/tests/instruments/test_ship_underwater_st.py b/tests/instruments/test_ship_underwater_st.py index 210e7340..9d44ee6d 100644 --- a/tests/instruments/test_ship_underwater_st.py +++ b/tests/instruments/test_ship_underwater_st.py @@ -6,8 +6,8 @@ import xarray as xr from parcels import FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.ship_underwater_st import simulate_ship_underwater_st +from virtualship.models import Location, Spacetime def test_simulate_ship_underwater_st(tmpdir) -> None: diff --git a/tests/instruments/test_xbt.py b/tests/instruments/test_xbt.py index 232e0c8b..97e33ade 100644 --- a/tests/instruments/test_xbt.py +++ b/tests/instruments/test_xbt.py @@ -11,8 +11,8 @@ import xarray as xr from parcels import Field, FieldSet -from virtualship import Location, Spacetime from virtualship.instruments.xbt import XBT, simulate_xbt +from virtualship.models import Location, Spacetime def test_simulate_xbts(tmpdir) -> None: diff --git a/tests/test_mfp_to_yaml.py b/tests/test_mfp_to_yaml.py index 3ef511f5..e230d2db 100644 --- a/tests/test_mfp_to_yaml.py +++ b/tests/test_mfp_to_yaml.py @@ -3,8 +3,7 @@ import pandas as pd import pytest -from virtualship.expedition.schedule import Schedule -from virtualship.expedition.ship_config import InstrumentType +from virtualship.models import InstrumentType, Schedule from virtualship.utils import mfp_to_yaml diff --git a/tests/test_utils.py b/tests/test_utils.py index b0d00be9..4c6db8fc 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,4 +1,4 @@ -from virtualship.expedition import Schedule, ShipConfig +from virtualship.models import Schedule, ShipConfig from virtualship.utils import get_example_config, get_example_schedule