diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cbc7f5572d..8b1e05be70 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -18,21 +18,16 @@ defaults: jobs: unit-test: - name: "py${{ matrix.python-version }} | ${{ matrix.os }} | unit tests (${{ matrix.test-subfolder }})" + name: "py${{ matrix.python-version }} | ${{ matrix.os }} | unit tests" runs-on: ${{ matrix.os }}-latest strategy: fail-fast: false matrix: os: [ubuntu] #, mac, windows] # TODO v4: Re-enable windows and mac - test-subfolder: ["/"] python-version: ["3.12"] include: - os: ubuntu python-version: "3.11" - test-subfolder: "/" - - os: ubuntu - python-version: "3.12" - test-subfolder: "/v4" steps: - name: Checkout uses: actions/checkout@v4 @@ -43,7 +38,7 @@ jobs: python-version: ${{ matrix.python-version }} - name: Unit test run: | - coverage run -m pytest -v -s --html=${{ matrix.os }}_${{ matrix.python-version }}_unit_test_report.html --self-contained-html tests${{ matrix.test-subfolder }} + coverage run -m pytest -v -s --html=${{ matrix.os }}_${{ matrix.python-version }}_unit_test_report.html --self-contained-html coverage xml - name: Codecov uses: codecov/codecov-action@v5.3.1 @@ -58,6 +53,8 @@ jobs: name: Unittest report ${{ matrix.os }}-${{ matrix.python-version }} path: ${{ matrix.os }}_${{ matrix.python-version }}_unit_test_report.html integration-test: + # TODO v4: Re-enable the workflow once development has stabilized and we want to run integration tests again + if: false name: "py${{ matrix.python-version }} | ${{ matrix.os }} | integration tests" runs-on: ${{ matrix.os }}-latest strategy: @@ -111,6 +108,8 @@ jobs: pattern: "* report *" typechecking: name: mypy + # TODO v4: Enable typechecking again + if: false runs-on: ubuntu-latest steps: - name: Checkout diff --git a/parcels/_core/utils/time.py b/parcels/_core/utils/time.py index 76d35cf838..64623eba15 100644 --- a/parcels/_core/utils/time.py +++ b/parcels/_core/utils/time.py @@ -6,10 +6,10 @@ import cftime import numpy as np -T = TypeVar("T", datetime, cftime.datetime) - if TYPE_CHECKING: - from parcels._typing import DatetimeLike + from parcels._typing import TimeLike + +T = TypeVar("T", bound="TimeLike") class TimeInterval: @@ -92,7 +92,7 @@ def is_compatible( def get_datetime_type_calendar( - example_datetime: DatetimeLike, + example_datetime: TimeLike, ) -> tuple[type, str | None]: """Get the type and calendar of a datetime object. diff --git a/parcels/_core/utils/unstructured.py b/parcels/_core/utils/unstructured.py index 76c4c93d7f..26a339a6df 100644 --- a/parcels/_core/utils/unstructured.py +++ b/parcels/_core/utils/unstructured.py @@ -1,12 +1,10 @@ -from collections.abc import Hashable - DIM_TO_VERTICAL_LOCATION_MAP = { "nz1": "center", "nz": "face", } -def get_vertical_location_from_dims(dims: tuple[Hashable, ...]): +def get_vertical_location_from_dims(dims: tuple[str, ...]): """ Determine the vertical location of the field based on the uxarray.UxDataArray object variables. diff --git a/parcels/_index_search.py b/parcels/_index_search.py index ca82359451..747ee2b186 100644 --- a/parcels/_index_search.py +++ b/parcels/_index_search.py @@ -356,7 +356,7 @@ def _search_indices_curvilinear_2d( ## TODO : Still need to implement the search_indices_curvilinear -def _search_indices_curvilinear(field: Field, time, z, y, x, ti, particle=None, search2D=False): +def _search_indices_curvilinear(field, time, z, y, x, ti, particle=None, search2D=False): if particle: zi, yi, xi = field.unravel_index(particle.ei) else: diff --git a/parcels/_typing.py b/parcels/_typing.py index cfa96dd376..7c2e12b8fd 100644 --- a/parcels/_typing.py +++ b/parcels/_typing.py @@ -34,7 +34,7 @@ VectorType = Literal["3D", "3DSigma", "2D"] | None # corresponds with `vector_type` GridIndexingType = Literal["pop", "mom5", "mitgcm", "nemo", "croco"] # corresponds with `gridindexingtype` NetcdfEngine = Literal["netcdf4", "xarray", "scipy"] -DatetimeLike = datetime | cftime_datetime | np.datetime64 +TimeLike = datetime | cftime_datetime | np.datetime64 KernelFunction = Callable[..., None] diff --git a/parcels/fieldset.py b/parcels/fieldset.py index 572c0224d8..fbb3055668 100644 --- a/parcels/fieldset.py +++ b/parcels/fieldset.py @@ -15,7 +15,7 @@ from parcels.xgrid import XGrid if TYPE_CHECKING: - from parcels._typing import DatetimeLike + from parcels._typing import TimeLike from parcels.basegrid import BaseGrid __all__ = ["FieldSet"] @@ -57,7 +57,7 @@ def __init__(self, fields: list[Field | VectorField]): assert_compatible_calendars(fields) self.fields = {f.name: f for f in fields} - self.constants = {} + self.constants: dict[str, float] = {} def __getattr__(self, name): """Get the field by name. If the field is not found, check if it's a constant.""" @@ -236,7 +236,7 @@ class CalendarError(Exception): # TODO: Move to a parcels errors module """Exception raised when the calendar of a field is not compatible with the rest of the Fields. The user should ensure that they only add fields to a FieldSet that have compatible CFtime calendars.""" -def assert_compatible_calendars(fields: Iterable[Field]): +def assert_compatible_calendars(fields: Iterable[Field | VectorField]): time_intervals = [f.time_interval for f in fields if f.time_interval is not None] if len(time_intervals) == 0: # All time intervals are none @@ -253,7 +253,7 @@ def assert_compatible_calendars(fields: Iterable[Field]): raise CalendarError(msg) -def _datetime_to_msg(example_datetime: DatetimeLike) -> str: +def _datetime_to_msg(example_datetime: TimeLike) -> str: datetime_type, calendar = get_datetime_type_calendar(example_datetime) msg = str(datetime_type) if calendar is not None: @@ -261,5 +261,5 @@ def _datetime_to_msg(example_datetime: DatetimeLike) -> str: return msg -def _format_calendar_error_message(field: Field, reference_datetime: DatetimeLike) -> str: +def _format_calendar_error_message(field: Field, reference_datetime: TimeLike) -> str: return f"Expected field {field.name!r} to have calendar compatible with datetime object {_datetime_to_msg(reference_datetime)}. Got field with calendar {_datetime_to_msg(field.time_interval.left)}. Have you considered using xarray to update the time dimension of the dataset to have a compatible calendar?" diff --git a/pyproject.toml b/pyproject.toml index b9d72bec0d..daee2826ce 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -119,7 +119,8 @@ local_scheme = "no-local-version" [tool.pytest.ini_options] addopts = ["--strict-config", "--strict-markers"] xfail_strict = true -testpaths = ["tests", "docs/examples"] +# testpaths = ["tests", "docs/examples"] # TODO v4: Re-enable once `tests/v4` separation is gone +testpaths = ["tests/v4"] python_files = ["test_*.py", "example_*.py", "*tutorial*"] minversion = "7" markers = [ # can be skipped by doing `pytest -m "not slow"` etc.