diff --git a/.github/workflows/black.yml b/.github/workflows/black.yml deleted file mode 100644 index 6b3664b4..00000000 --- a/.github/workflows/black.yml +++ /dev/null @@ -1,20 +0,0 @@ -name: Lint code with Black - -on: - push: - branches: [ "master", "stable-[0-9]+.[0-9]+" ] - pull_request: - branches: [ "master", "stable-[0-9]+.[0-9]+" ] - -jobs: - lint: - name: Lint code with Black - runs-on: ubuntu-latest - steps: - - name: Checkout sources - uses: actions/checkout@v4 - - - name: Run Black - uses: psf/black@stable - with: - version: "~= 24.0" \ No newline at end of file diff --git a/.github/workflows/release_and_publish.yml b/.github/workflows/release_and_publish.yml new file mode 100644 index 00000000..630852d3 --- /dev/null +++ b/.github/workflows/release_and_publish.yml @@ -0,0 +1,157 @@ +name: Release and Publish PyMEOS + +on: + push: + tags: + - "v[0-9]+.[0-9]+.[0-9]+*" + +jobs: + checks: + name: Make checks + runs-on: ubuntu-latest + + outputs: + is_alpha: ${{ steps.check_alpha.outputs.is_alpha }} + is_beta: ${{ steps.check_beta.outputs.is_beta }} + is_rc: ${{ steps.check_rc.outputs.is_rc }} + is_prerelease: ${{ steps.check_prerelease.outputs.is_prerelease }} + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Check if publishing an alpha version + id: check_alpha + run: | + VERSION=${GITHUB_REF#refs/tags/} + + if [[ $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+-alpha ]]; then + echo "Releasing an alpha version." + echo "is_alpha=true" >> "$GITHUB_OUTPUT" + else + echo "is_alpha=false" >> "$GITHUB_OUTPUT" + fi + + - name: Check if publishing a beta version + id: check_beta + run: | + VERSION=${GITHUB_REF#refs/tags/} + + if [[ $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+-beta ]]; then + echo "Releasing a beta version." + echo "is_beta=true" >> "$GITHUB_OUTPUT" + else + echo "is_beta=false" >> "$GITHUB_OUTPUT" + fi + + - name: Check if publishing a release candidate version + id: check_rc + run: | + VERSION=${GITHUB_REF#refs/tags/} + + if [[ $VERSION =~ ^v[0-9]+\.[0-9]+\.[0-9]+-rc ]]; then + echo "Releasing an rc version." + echo "is_rc=true" >> "$GITHUB_OUTPUT" + else + echo "is_rc=false" >> "$GITHUB_OUTPUT" + fi + + - name: Check if publishing a prerelease version + id: check_prerelease + run: | + is_alpha=${{ steps.check_alpha.outputs.is_alpha }} + is_beta=${{ steps.check_beta.outputs.is_beta }} + is_rc=${{ steps.check_rc.outputs.is_rc }} + + if [ "$is_alpha" == "true" ] || [ "$is_beta" == "true" ] || [ "$is_rc" == "true" ]; then + echo "Releasing an prerelease version." + echo "is_prerelease=true" >> "$GITHUB_OUTPUT" + else + echo "is_prerelease=false" >> "$GITHUB_OUTPUT" + fi + + - name: Check package version matches tag + run: | + tag_version=${GITHUB_REF#refs/tags/v} + python_version=$(grep -oP '__version__ = "\K[^"]+' pymeos/__init__.py) + + if [[ "$tag_version" != "$python_version" ]]; then + echo "Tag Version ($tag_version) doesn't match Code Version ($python_version)" + echo "::error title=Version mismatch::Tag Version ($tag_version) doesn't match Code Version ($python_version)" + exit 1 + fi + + + build: + name: Build PyMEOS + runs-on: ubuntu-latest + + steps: + - name: Checkout + uses: actions/checkout@v4 + + - name: Set up Python + uses: actions/setup-python@v3 + with: + python-version: 3.10 + cache: "pip" + + - name: Setup pip + run: | + python -m pip install --upgrade pip + python -m pip install build + + - name: Build package + run: python -m build + + - name: Upload artifacts + uses: actions/upload-artifact@v4 + with: + path: | + ./dist/pymeos-*.tar.gz + ./dist/pymeos-*.whl + + release: + name: Create GitHub Release + runs-on: ubuntu-latest + needs: [ checks, build ] + + permissions: + contents: write + + steps: + - name: Get artifacts + uses: actions/download-artifact@v4 + with: + path: ./dist + merge-multiple: true + + - name: Create Release + uses: softprops/action-gh-release@v2 + with: + files: ./dist/* + prerelease: ${{ needs.checks.outputs.is_prerelease }} + generate_release_notes: true + + publish: + name: Upload to PyPI + needs: [ build ] + runs-on: ubuntu-latest + + if: github.repository == 'MobilityDB/PyMEOS' + environment: + name: pypi + url: https://pypi.org/p/pymeos + permissions: + id-token: write + + steps: + - name: Get artifacts + uses: actions/download-artifact@v4 + with: + path: ./dist + merge-multiple: true + + - name: Publish to PyPI + uses: pypa/gh-action-pypi-publish@release/v1 + diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 00000000..981e8fd6 --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,26 @@ +name: Lint code with Ruff + +on: + push: + branches: [ "master", "stable-[0-9]+.[0-9]+" ] + pull_request: + branches: [ "master", "stable-[0-9]+.[0-9]+" ] + +jobs: + lint: + name: Lint code with Ruff + runs-on: ubuntu-latest + steps: + - name: Checkout sources + uses: actions/checkout@v4 + + - name: Install Ruff + uses: astral-sh/ruff-action@v3 + with: + args: "--version" + + - name: Check rules + run: "ruff check" + + - name: Check format + run: "ruff format --check --diff" diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index fc95eb68..e81bb384 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -23,12 +23,12 @@ jobs: strategy: fail-fast: false matrix: - python-version: [ "3.8", "3.9", "3.10", "3.11", "3.12" ] + python-version: [ "3.10", "3.11", "3.12", "3.13" ] os: [ ubuntu-latest, macos-13, macos-14 ] include: - - ld_path: "/usr/local/lib" + - ld_prefix: "/usr/local" - os: macos-14 - ld_path: "/opt/homebrew/lib" + ld_prefix: "/opt/homebrew" steps: - name: Checkout @@ -66,7 +66,7 @@ jobs: run: | mkdir MobilityDB/build cd MobilityDB/build - cmake .. -DMEOS=on + cmake .. -DMEOS=on -DCMAKE_INSTALL_PREFIX=${{ matrix.ld_prefix }} make -j sudo make install @@ -97,6 +97,6 @@ jobs: - name: Test PyMEOS with pytest run: | - export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{ matrix.ld_path }} - export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:${{ matrix.ld_path }} + export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${{ matrix.ld_prefix }}/lib + export DYLD_LIBRARY_PATH=$DYLD_LIBRARY_PATH:${{ matrix.ld_prefix }}/lib pytest diff --git a/README.md b/README.md index cf5809a4..4e7b5555 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,6 @@ [![pypi](https://img.shields.io/pypi/v/pymeos.svg)](https://pypi.python.org/pypi/pymeos/) [![docs status](https://readthedocs.org/projects/pymeos/badge/?version=latest)](https://pymeos.readthedocs.io/en/latest/) -[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black) [MEOS (Mobility Engine, Open Source)](https://www.libmeos.org/) is a C library which enables the manipulation of temporal and spatio-temporal data based on [MobilityDB](https://mobilitydb.com/)'s data types and functions. diff --git a/dev-requirements.txt b/dev-requirements.txt index c1600ba6..674c96cd 100644 --- a/dev-requirements.txt +++ b/dev-requirements.txt @@ -1,4 +1,5 @@ python-dateutil shapely geopandas -pytest \ No newline at end of file +pytest +ruff \ No newline at end of file diff --git a/docs/conf.py b/docs/conf.py index 646778b0..4ab7c3bc 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -70,6 +70,4 @@ def download_file(url, dest_path): prefix = "https://raw.githubusercontent.com/MobilityDB/PyMEOS-Examples/main/" download_file(f"{prefix}PyMEOS_Examples/AIS.ipynb", "src/examples/AIS.ipynb") -download_file( - f"{prefix}PyMEOS_Examples/BerlinMOD.ipynb", "src/examples/BerlinMOD.ipynb" -) +download_file(f"{prefix}PyMEOS_Examples/BerlinMOD.ipynb", "src/examples/BerlinMOD.ipynb") diff --git a/pymeos/__init__.py b/pymeos/__init__.py index fcf085a1..1924c21b 100644 --- a/pymeos/__init__.py +++ b/pymeos/__init__.py @@ -1,34 +1,35 @@ -from .aggregators import * -from .boxes import * -from .main import * -from .meos_init import * -from .temporal import * -from .collections import * from pymeos_cffi import ( - MeosException, - MeosInternalError, - MeosArgumentError, - MeosIoError, - MeosInternalTypeError, - MeosValueOutOfRangeError, - MeosDivisionByZeroError, - MeosMemoryAllocError, MeosAggregationError, + MeosArgumentError, MeosDirectoryError, + MeosDivisionByZeroError, + MeosException, MeosFileError, + MeosGeoJsonInputError, + MeosGeoJsonOutputError, + MeosInternalError, + MeosInternalTypeError, MeosInvalidArgError, MeosInvalidArgTypeError, MeosInvalidArgValueError, + MeosIoError, + MeosMemoryAllocError, MeosMfJsonInputError, MeosMfJsonOutputError, MeosTextInputError, MeosTextOutputError, + MeosValueOutOfRangeError, MeosWkbInputError, MeosWkbOutputError, - MeosGeoJsonInputError, - MeosGeoJsonOutputError, ) +from .aggregators import * +from .boxes import * +from .collections import * +from .main import * +from .meos_init import * +from .temporal import * + __version__ = "1.3.0-alpha-1" __all__ = [ # initialization diff --git a/pymeos/aggregators/__init__.py b/pymeos/aggregators/__init__.py index 1373961b..14d0f140 100644 --- a/pymeos/aggregators/__init__.py +++ b/pymeos/aggregators/__init__.py @@ -1,8 +1,8 @@ from .bool_aggregators import * from .general_aggregators import * from .number_aggregators import * -from .text_aggregators import * from .point_aggregators import * +from .text_aggregators import * from .time_aggregators import * __all__ = [ diff --git a/pymeos/aggregators/aggregator.py b/pymeos/aggregators/aggregator.py index ebe1f249..be86e04d 100644 --- a/pymeos/aggregators/aggregator.py +++ b/pymeos/aggregators/aggregator.py @@ -1,18 +1,19 @@ from __future__ import annotations import abc +from collections.abc import Callable from datetime import datetime, timedelta -from typing import Optional, Union, List, Generic, TypeVar, Callable +from typing import Generic, TypeVar from pymeos_cffi import * from ..boxes import Box +from ..collections import Time from ..factory import _TemporalFactory from ..temporal import Temporal -from ..collections import Time -ResultType = TypeVar("ResultType", bound=Union[Temporal, Time, Box]) -SourceType = TypeVar("SourceType", bound=Union[Temporal, Time, Box]) +ResultType = TypeVar("ResultType", bound=Temporal | Time | Box) +SourceType = TypeVar("SourceType", bound=Temporal | Time | Box) StateType = TypeVar("StateType") SourceMeosType = TypeVar("SourceMeosType") ResultMeosType = TypeVar("ResultMeosType") @@ -33,9 +34,7 @@ class BaseAggregator(Generic[SourceType, ResultType], abc.ABC): """ @staticmethod - def _add_function( - state: Optional[StateType], meos_object: SourceMeosType - ) -> StateType: + def _add_function(state: StateType | None, meos_object: SourceMeosType) -> StateType: """ Add `meos_object` to the aggregation. Usually a MEOS function. Args: @@ -46,7 +45,7 @@ def _add_function( New state of the aggregation after adding `meos_object`. """ - raise NotImplemented + raise NotImplementedError @staticmethod def _final_function(state: StateType) -> ResultMeosType: @@ -62,7 +61,7 @@ def _final_function(state: StateType) -> ResultMeosType: return temporal_tagg_finalfn(state) @classmethod - def _add(cls, state: Optional[StateType], temporal: SourceType) -> StateType: + def _add(cls, state: StateType | None, temporal: SourceType) -> StateType: """ Add the `temporal` object to the aggregation. Args: @@ -90,7 +89,7 @@ def _finish(cls, state) -> ResultType: return _TemporalFactory.create_temporal(result) @classmethod - def aggregate(cls, temporals: List[SourceType]) -> ResultType: + def aggregate(cls, temporals: list[SourceType]) -> ResultType: """ Aggregate a list of PyMEOS object at once. @@ -189,7 +188,7 @@ class BaseGranularAggregator(Generic[SourceType, ResultType, IntervalType, Origi @staticmethod def _add_function( - state: Optional[StateType], + state: StateType | None, meos_object: SourceMeosType, interval: IntervalType, origin: OriginType, @@ -206,7 +205,7 @@ def _add_function( New state of the aggregation after adding `meos_object`. """ - raise NotImplemented + raise NotImplementedError @staticmethod def _final_function(state: StateType) -> ResultMeosType: @@ -224,7 +223,7 @@ def _final_function(state: StateType) -> ResultMeosType: @classmethod def _add( cls, - state: Optional[StateType], + state: StateType | None, temporal: SourceType, interval: IntervalType, origin: OriginType, @@ -244,16 +243,14 @@ def _add( interval_converted = ( timedelta_to_interval(interval) if isinstance(interval, timedelta) - else pg_interval_in(interval, -1) if isinstance(interval, str) else None + else pg_interval_in(interval, -1) + if isinstance(interval, str) + else None ) origin_converted = ( - datetime_to_timestamptz(origin) - if isinstance(origin, datetime) - else pg_timestamptz_in(origin, -1) - ) - return cls._add_function( - state, temporal._inner, interval_converted, origin_converted + datetime_to_timestamptz(origin) if isinstance(origin, datetime) else pg_timestamptz_in(origin, -1) ) + return cls._add_function(state, temporal._inner, interval_converted, origin_converted) @classmethod def _finish(cls, state: StateType) -> ResultType: @@ -270,9 +267,7 @@ def _finish(cls, state: StateType) -> ResultType: return _TemporalFactory.create_temporal(result) @classmethod - def aggregate( - cls, temporals: List[SourceType], interval: IntervalType, origin: OriginType - ) -> ResultType: + def aggregate(cls, temporals: list[SourceType], interval: IntervalType, origin: OriginType) -> ResultType: """ Aggregate a list of PyMEOS object at once with certain granularity. @@ -322,9 +317,7 @@ class GranularAggregation( def __init__( self, - add_function: Callable[ - [Optional[StateType], SourceType, IntervalType, OriginType], StateType - ], + add_function: Callable[[StateType | None, SourceType, IntervalType, OriginType], StateType], finish_function: Callable[[StateType], ResultType], interval: IntervalType, origin: OriginType, @@ -334,7 +327,5 @@ def __init__( self._origin = origin def add(self: SelfAgg, new_temporal: SourceType) -> SelfAgg: - self._state = self._add_function( - self._state, new_temporal, self._interval, self._origin - ) + self._state = self._add_function(self._state, new_temporal, self._interval, self._origin) return self diff --git a/pymeos/aggregators/bool_aggregators.py b/pymeos/aggregators/bool_aggregators.py index 38e2e31b..b6a90060 100644 --- a/pymeos/aggregators/bool_aggregators.py +++ b/pymeos/aggregators/bool_aggregators.py @@ -1,7 +1,7 @@ from pymeos_cffi import * -from .aggregator import BaseAggregator from ..main import TBool +from .aggregator import BaseAggregator class TemporalAndAggregator(BaseAggregator[TBool, TBool]): diff --git a/pymeos/aggregators/general_aggregators.py b/pymeos/aggregators/general_aggregators.py index d50d4486..39a4970e 100644 --- a/pymeos/aggregators/general_aggregators.py +++ b/pymeos/aggregators/general_aggregators.py @@ -1,30 +1,27 @@ from datetime import datetime -from typing import Union from pymeos_cffi import ( - timestamptz_tcount_transfn, datetime_to_timestamptz, - tstzset_tcount_transfn, - temporal_tcount_transfn, - tstzspan_tcount_transfn, - tstzspanset_tcount_transfn, - temporal_extent_transfn, - timestamptz_extent_transfn, set_extent_transfn, span_extent_transfn, spanset_extent_transfn, + temporal_extent_transfn, + temporal_tcount_transfn, + timestamptz_extent_transfn, + timestamptz_tcount_transfn, + tstzset_tcount_transfn, + tstzspan_tcount_transfn, + tstzspanset_tcount_transfn, ) -from .aggregator import BaseAggregator from ..boxes import Box from ..collections import Time, TsTzSet, TsTzSpan, TsTzSpanSet from ..main import TIntSeq, TIntSeqSet from ..temporal import Temporal, TInterpolation +from .aggregator import BaseAggregator -class TemporalInstantCountAggregator( - BaseAggregator[Union[datetime, TsTzSet, Temporal], TIntSeq] -): +class TemporalInstantCountAggregator(BaseAggregator[datetime | TsTzSet | Temporal, TIntSeq]): """ Temporal count for instantaneous temporal objects: @@ -42,19 +39,14 @@ def _add(cls, state, temporal): state = timestamptz_tcount_transfn(state, datetime_to_timestamptz(temporal)) elif isinstance(temporal, TsTzSet): state = tstzset_tcount_transfn(state, temporal._inner) - elif ( - isinstance(temporal, Temporal) - and temporal.interpolation() == TInterpolation.DISCRETE - ): + elif isinstance(temporal, Temporal) and temporal.interpolation() == TInterpolation.DISCRETE: state = temporal_tcount_transfn(state, temporal._inner) else: cls._error(temporal) return state -class TemporalPeriodCountAggregator( - BaseAggregator[Union[TsTzSpan, TsTzSpanSet, Temporal], TIntSeqSet] -): +class TemporalPeriodCountAggregator(BaseAggregator[TsTzSpan | TsTzSpanSet | Temporal, TIntSeqSet]): """ Temporal count for non-instantaneous temporal objects: @@ -72,17 +64,14 @@ def _add(cls, state, temporal): state = tstzspan_tcount_transfn(state, temporal._inner) elif isinstance(temporal, TsTzSpanSet): state = tstzspanset_tcount_transfn(state, temporal._inner) - elif ( - isinstance(temporal, Temporal) - and temporal.interpolation() != TInterpolation.DISCRETE - ): + elif isinstance(temporal, Temporal) and temporal.interpolation() != TInterpolation.DISCRETE: state = temporal_tcount_transfn(state, temporal._inner) else: cls._error(temporal) return state -class TemporalExtentAggregator(BaseAggregator[Union[Time, Temporal], TsTzSpan]): +class TemporalExtentAggregator(BaseAggregator[Time | Temporal, TsTzSpan]): """ Temporal extent of any kind of temporal object, i.e. smallest :class:`~pymeos.time.tstzspan.TsTzSpan` that includes all aggregated temporal objects. @@ -110,5 +99,5 @@ def _add(cls, state, temporal): return state @classmethod - def _finish(cls, state) -> Union[Temporal, Time, Box]: + def _finish(cls, state) -> Temporal | Time | Box: return TsTzSpan(_inner=state) diff --git a/pymeos/aggregators/number_aggregators.py b/pymeos/aggregators/number_aggregators.py index 1087f22e..a8bea3cc 100644 --- a/pymeos/aggregators/number_aggregators.py +++ b/pymeos/aggregators/number_aggregators.py @@ -1,8 +1,8 @@ from pymeos_cffi import * -from .aggregator import BaseAggregator from ..boxes import TBox -from ..main import TInt, TFloat, TNumber +from ..main import TFloat, TInt, TNumber +from .aggregator import BaseAggregator class TemporalAverageAggregator(BaseAggregator[TNumber, TNumber]): diff --git a/pymeos/aggregators/point_aggregators.py b/pymeos/aggregators/point_aggregators.py index 0969f1a9..794218f3 100644 --- a/pymeos/aggregators/point_aggregators.py +++ b/pymeos/aggregators/point_aggregators.py @@ -1,8 +1,8 @@ -from pymeos_cffi import * +from pymeos_cffi import tspatial_extent_transfn -from .aggregator import BaseAggregator from ..boxes import STBox from ..main import TPoint +from .aggregator import BaseAggregator class TemporalPointExtentAggregator(BaseAggregator[TPoint, STBox]): @@ -11,10 +11,10 @@ class TemporalPointExtentAggregator(BaseAggregator[TPoint, STBox]): includes all aggregated temporal numbers. MEOS Functions: - tpoint_extent_transfn, temporal_tagg_finalfn + tspatial_extent_transfn, temporal_tagg_finalfn """ - _add_function = tpoint_extent_transfn + _add_function = tspatial_extent_transfn @classmethod def _finish(cls, state) -> STBox: diff --git a/pymeos/aggregators/text_aggregators.py b/pymeos/aggregators/text_aggregators.py index 9060b801..904fbd7d 100644 --- a/pymeos/aggregators/text_aggregators.py +++ b/pymeos/aggregators/text_aggregators.py @@ -1,7 +1,7 @@ from pymeos_cffi import * -from .aggregator import BaseAggregator from ..main import TText +from .aggregator import BaseAggregator class TemporalTextMaxAggregator(BaseAggregator[TText, TText]): diff --git a/pymeos/aggregators/time_aggregators.py b/pymeos/aggregators/time_aggregators.py index 72a88a6b..159503d4 100644 --- a/pymeos/aggregators/time_aggregators.py +++ b/pymeos/aggregators/time_aggregators.py @@ -1,22 +1,19 @@ from datetime import datetime -from typing import Union from pymeos_cffi import ( - timestamptz_union_transfn, datetime_to_timestamptz, - set_union_transfn, set_union_finalfn, + set_union_transfn, + timestamptz_union_transfn, union_spanset_span, union_spanset_spanset, ) -from .aggregator import BaseAggregator from ..collections import TsTzSet, TsTzSpan, TsTzSpanSet +from .aggregator import BaseAggregator -class TimeInstantaneousUnionAggregator( - BaseAggregator[Union[datetime, TsTzSet], TsTzSet] -): +class TimeInstantaneousUnionAggregator(BaseAggregator[datetime | TsTzSet, TsTzSet]): """ Temporal union of instantaneous time objects (:class:'~datetime.datetime' and :class:`~pymeos.time.tstzset.TsTzSet`). @@ -41,9 +38,7 @@ def _finish(cls, state) -> TsTzSet: return TsTzSet(_inner=result) -class TimeContinuousUnionAggregator( - BaseAggregator[Union[TsTzSpan, TsTzSpanSet], TsTzSpanSet] -): +class TimeContinuousUnionAggregator(BaseAggregator[TsTzSpan | TsTzSpanSet, TsTzSpanSet]): """ Temporal union of continuous time objects (:class:`~pymeos.time.tstzspan.TsTzSpan` and :class:`~pymeos.time.tstzspanset.TsTzSpanSet`). diff --git a/pymeos/boxes/box.py b/pymeos/boxes/box.py index 5a2aa52a..2fbbcd1e 100644 --- a/pymeos/boxes/box.py +++ b/pymeos/boxes/box.py @@ -1,12 +1,10 @@ -from typing import Union - from .stbox import STBox from .tbox import TBox -Box = Union[TBox, STBox] +Box = TBox | STBox """ -Union type that includes all Box types in PyMEOS: +Union type that includes all Box types in PyMEOS: -- :class:`~pymeos.boxes.tbox.TBox` for numeric temporal boxes. +- :class:`~pymeos.boxes.tbox.TBox` for numeric temporal boxes. - :class:`~pymeos.boxes.stbox.STBox` for spatio-temporal boxes. """ diff --git a/pymeos/boxes/stbox.py b/pymeos/boxes/stbox.py index 1eec7b80..9d24f7bc 100644 --- a/pymeos/boxes/stbox.py +++ b/pymeos/boxes/stbox.py @@ -1,13 +1,13 @@ from __future__ import annotations -from typing import Optional, Union, List, TYPE_CHECKING +from typing import TYPE_CHECKING import shapely.geometry.base as shp from pymeos_cffi import * +from ..collections import * from ..main import TPoint from ..temporal import Temporal -from ..collections import * if TYPE_CHECKING: from .box import Box @@ -42,7 +42,7 @@ class STBox: def _get_box( self, - other: Union[shp.BaseGeometry, STBox, Temporal, Time], + other: shp.BaseGeometry | STBox | Temporal | Time, allow_space_only: bool = True, allow_time_only: bool = False, ) -> STBox: @@ -51,7 +51,7 @@ def _get_box( elif isinstance(other, STBox): other_box = other._inner elif isinstance(other, TPoint): - other_box = tpoint_to_stbox(other._inner) + other_box = tspatial_to_stbox(other._inner) elif allow_time_only and isinstance(other, Temporal): other_box = tstzspan_to_stbox(temporal_to_tstzspan(other._inner)) elif allow_time_only and isinstance(other, datetime): @@ -69,29 +69,24 @@ def _get_box( # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - xmin: Optional[Union[str, float]] = None, - xmax: Optional[Union[str, float]] = None, - ymin: Optional[Union[str, float]] = None, - ymax: Optional[Union[str, float]] = None, - zmin: Optional[Union[str, float]] = None, - zmax: Optional[Union[str, float]] = None, - tmin: Optional[Union[str, datetime]] = None, - tmax: Optional[Union[str, datetime]] = None, + xmin: str | float | None = None, + xmax: str | float | None = None, + ymin: str | float | None = None, + ymax: str | float | None = None, + zmin: str | float | None = None, + zmax: str | float | None = None, + tmin: str | datetime | None = None, + tmax: str | datetime | None = None, tmin_inc: bool = True, tmax_inc: bool = True, geodetic: bool = False, - srid: Optional[int] = None, + srid: int | None = None, _inner=None, ): assert (_inner is not None) or (string is not None) != ( - ( - xmin is not None - and xmax is not None - and ymin is not None - and ymax is not None - ) + (xmin is not None and xmax is not None and ymin is not None and ymax is not None) or (tmin is not None and tmax is not None) ), ( "Either string must be not None or at least a bound pair (xmin/max" @@ -105,17 +100,10 @@ def __init__( else: tstzspan = None hast = tmin is not None and tmax is not None - hasx = ( - xmin is not None - and xmax is not None - and ymin is not None - and ymax is not None - ) + hasx = xmin is not None and xmax is not None and ymin is not None and ymax is not None hasz = zmin is not None and zmax is not None if hast: - tstzspan = TsTzSpan( - lower=tmin, upper=tmax, lower_inc=tmin_inc, upper_inc=tmax_inc - )._inner + tstzspan = TsTzSpan(lower=tmin, upper=tmax, lower_inc=tmin_inc, upper_inc=tmax_inc)._inner self._inner = stbox_make( hasx, hasz, @@ -225,7 +213,7 @@ def from_time(time: Time) -> STBox: @staticmethod def from_geometry_time( geometry: shp.BaseGeometry, - time: Union[datetime, TsTzSpan], + time: datetime | TsTzSpan, geodetic: bool = False, ) -> STBox: """ @@ -248,10 +236,7 @@ def from_geometry_time( elif isinstance(time, TsTzSpan): result = geo_tstzspan_to_stbox(gs, time._inner) else: - raise TypeError( - f"Operation not supported with types " - f"{geometry.__class__} and {time.__class__}" - ) + raise TypeError(f"Operation not supported with types {geometry.__class__} and {time.__class__}") return STBox(_inner=result) @staticmethod @@ -266,15 +251,15 @@ def from_tpoint(temporal: TPoint) -> STBox: A new :class:`STBox` instance. MEOS Functions: - tpoint_to_stbox + tspatial_to_stbox """ - return STBox(_inner=tpoint_to_stbox(temporal._inner)) + return STBox(_inner=tspatial_to_stbox(temporal._inner)) @staticmethod def from_expanding_bounding_box( - value: Union[shp.BaseGeometry, TPoint, STBox], + value: shp.BaseGeometry | TPoint | STBox, expansion: float, - geodetic: Optional[bool] = False, + geodetic: bool | None = False, ) -> STBox: """ Returns a `STBox` from a `shp.BaseGeometry`, `TPoint` or `STBox` instance, @@ -294,14 +279,14 @@ def from_expanding_bounding_box( """ if isinstance(value, shp.BaseGeometry): gs = geo_to_gserialized(value, geodetic) - result = geo_expand_space(gs, expansion) + box = geo_to_stbox(gs) elif isinstance(value, TPoint): - result = tpoint_expand_space(value._inner, expansion) + box = tspatial_to_stbox(value._inner) elif isinstance(value, STBox): - result = stbox_expand_space(value._inner, expansion) + box = value._inner else: raise TypeError(f"Operation not supported with type {value.__class__}") - return STBox(_inner=result) + return STBox(_inner=stbox_expand_space(box, expansion)) # ------------------------- Output ---------------------------------------- def __str__(self, max_decimals: int = 15): @@ -326,7 +311,7 @@ def __repr__(self): MEOS Functions: stbox_out """ - return f"{self.__class__.__name__}" f"({self})" + return f"{self.__class__.__name__}({self})" def as_wkb(self) -> bytes: """ @@ -431,7 +416,7 @@ def geodetic(self) -> bool: """ return stbox_isgeodetic(self._inner) - def xmin(self) -> Optional[float]: + def xmin(self) -> float | None: """ Returns the minimum X coordinate of ``self``. @@ -443,7 +428,7 @@ def xmin(self) -> Optional[float]: """ return stbox_xmin(self._inner) - def ymin(self) -> Optional[float]: + def ymin(self) -> float | None: """ Returns the minimum Y coordinate of ``self``. @@ -455,7 +440,7 @@ def ymin(self) -> Optional[float]: """ return stbox_ymin(self._inner) - def zmin(self) -> Optional[float]: + def zmin(self) -> float | None: """ Returns the minimum Z coordinate of ``self``. @@ -467,7 +452,7 @@ def zmin(self) -> Optional[float]: """ return stbox_zmin(self._inner) - def tmin(self) -> Optional[datetime]: + def tmin(self) -> datetime | None: """ Returns the starting time of ``self``. @@ -493,7 +478,7 @@ def tmin_inc(self) -> bool: """ return stbox_tmin_inc(self._inner) - def xmax(self) -> Optional[float]: + def xmax(self) -> float | None: """ Returns the maximum X coordinate of ``self``. @@ -505,7 +490,7 @@ def xmax(self) -> Optional[float]: """ return stbox_xmax(self._inner) - def ymax(self) -> Optional[float]: + def ymax(self) -> float | None: """ Returns the maximum Y coordinate of ``self``. @@ -517,7 +502,7 @@ def ymax(self) -> Optional[float]: """ return stbox_ymax(self._inner) - def zmax(self) -> Optional[float]: + def zmax(self) -> float | None: """ Returns the maximum Z coordinate of ``self``. @@ -529,7 +514,7 @@ def zmax(self) -> Optional[float]: """ return stbox_zmax(self._inner) - def tmax(self) -> Optional[datetime]: + def tmax(self) -> datetime | None: """ Returns the ending time of ``self``. @@ -597,7 +582,7 @@ def get_space(self) -> STBox: result = stbox_get_space(self._inner) return STBox(_inner=result) - def expand(self, other: Union[int, float, timedelta]) -> STBox: + def expand(self, other: int | float | timedelta) -> STBox: """ Expands ``self`` with `other`. If `other` is a :class:`int` or a :class:`float`, the result is equal @@ -615,7 +600,7 @@ def expand(self, other: Union[int, float, timedelta]) -> STBox: MEOS Functions: stbox_expand_space, stbox_expand_time """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = stbox_expand_space(self._inner, float(other)) elif isinstance(other, timedelta): result = stbox_expand_time(self._inner, timedelta_to_interval(other)) @@ -660,9 +645,7 @@ def scale_time(self, duration: timedelta) -> STBox: """ return self.shift_scale_time(duration=duration) - def shift_scale_time( - self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None - ) -> STBox: + def shift_scale_time(self, shift: timedelta | None = None, duration: timedelta | None = None) -> STBox: """ Returns a new `STBox` with the time dimension shifted by `shift` and with duration `duration`. @@ -680,9 +663,7 @@ def shift_scale_time( See Also: :meth:`TsTzSpan.shift_scale` """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" result = stbox_shift_scale_time( self._inner, timedelta_to_interval(shift) if shift else None, @@ -690,7 +671,7 @@ def shift_scale_time( ) return STBox(_inner=result) - def round(self, max_decimals: Optional[int] = 0) -> STBox: + def round(self, max_decimals: int | None = 0) -> STBox: """ Returns `self` rounded to the given number of decimal digits. @@ -724,7 +705,7 @@ def transform(self, srid: int) -> STBox: return STBox(_inner=result) # ------------------------- Set Operations -------------------------------- - def union(self, other: STBox, strict: Optional[bool] = False) -> STBox: + def union(self, other: STBox, strict: bool | None = False) -> STBox: """ Returns the union of `self` with `other`. @@ -757,7 +738,7 @@ def __add__(self, other): return self.union(other, False) # TODO: Check returning None for empty intersection is the desired behaviour - def intersection(self, other: STBox) -> Optional[STBox]: + def intersection(self, other: STBox) -> STBox | None: """ Returns the intersection of `self` with `other`. @@ -791,9 +772,7 @@ def __mul__(self, other): return self.intersection(other) # ------------------------- Topological Operations ------------------------ - def is_adjacent( - self, other: Union[shp.BaseGeometry, STBox, Temporal, Time] - ) -> bool: + def is_adjacent(self, other: shp.BaseGeometry | STBox | Temporal | Time) -> bool: """ Returns whether ``self`` and `other` are adjacent. Two spatiotemporal boxes are adjacent if they share n dimensions and the intersection is @@ -810,13 +789,9 @@ def is_adjacent( MEOS Functions: adjacent_stbox_stbox """ - return adjacent_stbox_stbox( - self._inner, self._get_box(other, allow_time_only=True) - ) + return adjacent_stbox_stbox(self._inner, self._get_box(other, allow_time_only=True)) - def is_contained_in( - self, container: Union[shp.BaseGeometry, STBox, Temporal, Time] - ) -> bool: + def is_contained_in(self, container: shp.BaseGeometry | STBox | Temporal | Time) -> bool: """ Returns whether ``self`` is contained in `container`. Note that for `TPoint` instances, the bounding box of the temporal point is used. @@ -831,11 +806,9 @@ def is_contained_in( MEOS Functions: contained_stbox_stbox """ - return contained_stbox_stbox( - self._inner, self._get_box(container, allow_time_only=True) - ) + return contained_stbox_stbox(self._inner, self._get_box(container, allow_time_only=True)) - def contains(self, content: Union[shp.BaseGeometry, STBox, Temporal, Time]) -> bool: + def contains(self, content: shp.BaseGeometry | STBox | Temporal | Time) -> bool: """ Returns whether ``self`` contains `content`. Note that for `TPoint` instances, the bounding box of the temporal point is used. @@ -850,9 +823,7 @@ def contains(self, content: Union[shp.BaseGeometry, STBox, Temporal, Time]) -> b MEOS Functions: contains_stbox_stbox """ - return contains_stbox_stbox( - self._inner, self._get_box(content, allow_time_only=True) - ) + return contains_stbox_stbox(self._inner, self._get_box(content, allow_time_only=True)) def __contains__(self, item): """ @@ -873,7 +844,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps(self, other: Union[shp.BaseGeometry, STBox, Temporal, Time]) -> bool: + def overlaps(self, other: shp.BaseGeometry | STBox | Temporal | Time) -> bool: """ Returns whether ``self`` overlaps `other`. Note that for `TPoint` instances, the bounding box of the temporal point is used. @@ -887,11 +858,9 @@ def overlaps(self, other: Union[shp.BaseGeometry, STBox, Temporal, Time]) -> boo MEOS Functions: overlaps_stbox_stbox """ - return overlaps_stbox_stbox( - self._inner, self._get_box(other, allow_time_only=True) - ) + return overlaps_stbox_stbox(self._inner, self._get_box(other, allow_time_only=True)) - def is_same(self, other: Union[shp.BaseGeometry, STBox, Temporal, Time]) -> bool: + def is_same(self, other: shp.BaseGeometry | STBox | Temporal | Time) -> bool: """ Returns whether ``self`` is the same as `other`. Note that for `TPoint` instances, the bounding box of the temporal point is used. @@ -908,7 +877,7 @@ def is_same(self, other: Union[shp.BaseGeometry, STBox, Temporal, Time]) -> bool return same_stbox_stbox(self._inner, self._get_box(other, allow_time_only=True)) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_left(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is strictly to the left of `other`. Checks the X dimension. @@ -925,7 +894,7 @@ def is_left(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: """ return left_stbox_stbox(self._inner, self._get_box(other)) - def is_over_or_left(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_over_or_left(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is to the left `other` allowing for overlap. That is, ``self`` does not extend to the right of `other`. Checks the @@ -939,11 +908,11 @@ def is_over_or_left(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool overlap, ``False`` otherwise. MEOS Functions: - overleft_stbox_stbox, tpoint_to_stbox + overleft_stbox_stbox, tspatial_to_stbox """ return overleft_stbox_stbox(self._inner, self._get_box(other)) - def is_right(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_right(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is strictly to the right of `other`. Checks the X dimension. @@ -960,7 +929,7 @@ def is_right(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: """ return right_stbox_stbox(self._inner, self._get_box(other)) - def is_over_or_right(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_over_or_right(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is to the right of `other` allowing for overlap. That is, ``self`` does not extend to the left of `other`. @@ -978,7 +947,7 @@ def is_over_or_right(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> boo """ return overright_stbox_stbox(self._inner, self._get_box(other)) - def is_below(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_below(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is strictly below `other`. Checks the Y dimension. @@ -995,7 +964,7 @@ def is_below(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: """ return below_stbox_stbox(self._inner, self._get_box(other)) - def is_over_or_below(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_over_or_below(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is below `other` allowing for overlap. That is, ``self`` does not extend above `other`. Checks the Y dimension. @@ -1012,7 +981,7 @@ def is_over_or_below(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> boo """ return overbelow_stbox_stbox(self._inner, self._get_box(other)) - def is_above(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_above(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is strictly above `other`. Checks the Y dimension. @@ -1029,7 +998,7 @@ def is_above(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: """ return above_stbox_stbox(self._inner, self._get_box(other)) - def is_over_or_above(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_over_or_above(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is above `other` allowing for overlap. That is, ``self`` does not extend below `other`. @@ -1047,7 +1016,7 @@ def is_over_or_above(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> boo """ return overabove_stbox_stbox(self._inner, self._get_box(other)) - def is_front(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_front(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is strictly in front of `other`. Checks the Z dimension. @@ -1064,7 +1033,7 @@ def is_front(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: """ return front_stbox_stbox(self._inner, self._get_box(other)) - def is_over_or_front(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_over_or_front(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is in front of `other` allowing for overlap. That is, ``self`` does not extend behind `other`. @@ -1082,7 +1051,7 @@ def is_over_or_front(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> boo """ return overfront_stbox_stbox(self._inner, self._get_box(other)) - def is_behind(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_behind(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is strictly behind `other`. Checks the Z dimension. @@ -1099,7 +1068,7 @@ def is_behind(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: """ return back_stbox_stbox(self._inner, self._get_box(other)) - def is_over_or_behind(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bool: + def is_over_or_behind(self, other: shp.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether ``self`` is behind `other` allowing for overlap. That is, ``self`` does not extend in front of `other`. @@ -1117,7 +1086,7 @@ def is_over_or_behind(self, other: Union[shp.BaseGeometry, STBox, TPoint]) -> bo """ return overback_stbox_stbox(self._inner, self._get_box(other)) - def is_before(self, other: Union[Box, Temporal, Time]) -> bool: + def is_before(self, other: Box | Temporal | Time) -> bool: """ Returns whether ``self`` is strictly before `other`. Checks the time dimension. @@ -1131,7 +1100,7 @@ def is_before(self, other: Union[Box, Temporal, Time]) -> bool: """ return self.to_tstzspan().is_before(other) - def is_over_or_before(self, other: Union[Box, Temporal, Time]) -> bool: + def is_over_or_before(self, other: Box | Temporal | Time) -> bool: """ Returns whether ``self`` is before `other` allowing for overlap. That is, ``self`` does not extend after `other`. @@ -1146,7 +1115,7 @@ def is_over_or_before(self, other: Union[Box, Temporal, Time]) -> bool: """ return self.to_tstzspan().is_over_or_before(other) - def is_after(self, other: Union[Box, Temporal, Time]) -> bool: + def is_after(self, other: Box | Temporal | Time) -> bool: """ Returns whether ``self`` is strictly after `other`. Checks the time dimension. @@ -1160,7 +1129,7 @@ def is_after(self, other: Union[Box, Temporal, Time]) -> bool: """ return self.to_tstzspan().is_after(other) - def is_over_or_after(self, other: Union[Box, Temporal, Time]) -> bool: + def is_over_or_after(self, other: Box | Temporal | Time) -> bool: """ Returns whether ``self`` is after `other` allowing for overlap. That is, ``self`` does not extend before `other`. @@ -1176,9 +1145,7 @@ def is_over_or_after(self, other: Union[Box, Temporal, Time]) -> bool: return self.to_tstzspan().is_over_or_after(other) # ------------------------- Distance Operations --------------------------- - def nearest_approach_distance( - self, other: Union[shp.BaseGeometry, STBox, TPoint] - ) -> float: + def nearest_approach_distance(self, other: shp.BaseGeometry | STBox | TPoint) -> float: """ Returns the distance between the nearest points of ``self`` and `other`. @@ -1203,7 +1170,7 @@ def nearest_approach_distance( raise TypeError(f"Operation not supported with type {other.__class__}") # ------------------------- Splitting -------------------------------------- - def quad_split_flat(self) -> List[STBox]: + def quad_split_flat(self) -> list[STBox]: """ Returns a list of 4 (or 8 if `self`has Z dimension) :class:`STBox` instances resulting from the quad split of ``self``. @@ -1227,7 +1194,7 @@ def quad_split_flat(self) -> List[STBox]: boxes, count = stbox_quad_split(self._inner) return [STBox(_inner=boxes + i) for i in range(count)] - def quad_split(self) -> Union[List[List[STBox]], List[List[List[STBox]]]]: + def quad_split(self) -> list[list[STBox]] | list[list[list[STBox]]]: """ Returns a 2D (YxX) or 3D (ZxYxX) list of :class:`STBox` instances resulting from the quad split of ``self``. @@ -1278,11 +1245,12 @@ def quad_split(self) -> Union[List[List[STBox]], List[List[List[STBox]]]]: def tile( self, - size: Optional[float] = None, - duration: Optional[Union[timedelta, str]] = None, - origin: Optional[shp.BaseGeometry] = None, - start: Union[datetime, str, None] = None, - ) -> List[STBox]: + size: float | None = None, + duration: timedelta | str | None = None, + origin: shp.BaseGeometry | None = None, + start: datetime | str | None = None, + border_inc: bool = True, + ) -> list[STBox]: """ Returns a list of `STBox` instances representing the tiles of ``self``. @@ -1298,6 +1266,7 @@ def tile( origin will be (0, 0, 0). start: The start time of the temporal tiling. If not provided, the start time used by default is Monday, January 3, 2000. + border_inc: Whether the border is inclusive or not. Returns: A list of `STBox` instances. @@ -1316,7 +1285,9 @@ def tile( dt = ( timedelta_to_interval(duration) if isinstance(duration, timedelta) - else pg_interval_in(duration, -1) if isinstance(duration, str) else None + else pg_interval_in(duration, -1) + if isinstance(duration, str) + else None ) st = ( datetime_to_timestamptz(start) @@ -1324,19 +1295,17 @@ def tile( else ( pg_timestamptz_in(start, -1) if isinstance(start, str) - else pg_timestamptz_in("2000-01-03", -1) if self.has_t() else 0 + else pg_timestamptz_in("2000-01-03", -1) + if self.has_t() + else 0 ) ) gs = ( geo_to_gserialized(origin, self.geodetic()) if origin is not None - else ( - pgis_geography_in("Point(0 0 0)", -1) - if self.geodetic() - else pgis_geometry_in("Point(0 0 0)", -1) - ) + else (pgis_geography_in("Point(0 0 0)", -1) if self.geodetic() else pgis_geometry_in("Point(0 0 0)", -1)) ) - tiles, count = stbox_space_time_tiles(self._inner, sz, sz, sz, dt, gs, st) + tiles, count = stbox_space_time_tiles(self._inner, sz, sz, sz, dt, gs, st, border_inc) return [STBox(_inner=tiles + i) for i in range(count)] # ------------------------- Comparisons ----------------------------------- diff --git a/pymeos/boxes/tbox.py b/pymeos/boxes/tbox.py index 70579571..336ecca1 100644 --- a/pymeos/boxes/tbox.py +++ b/pymeos/boxes/tbox.py @@ -1,11 +1,9 @@ from __future__ import annotations -from typing import Optional, Union, List - from pymeos_cffi import * from ..collections import * -from ..main import TNumber, TInt, TFloat +from ..main import TFloat, TInt, TNumber class TBox: @@ -55,12 +53,12 @@ def _is_float(self) -> bool: # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - xmin: Optional[Union[str, int, float]] = None, - xmax: Optional[Union[str, int, float]] = None, - tmin: Optional[Union[str, datetime]] = None, - tmax: Optional[Union[str, datetime]] = None, + xmin: str | int | float | None = None, + xmax: str | int | float | None = None, + tmin: str | datetime | None = None, + tmax: str | datetime | None = None, xmin_inc: bool = True, xmax_inc: bool = False, tmin_inc: bool = True, @@ -68,12 +66,8 @@ def __init__( _inner=None, ): assert (_inner is not None) or (string is not None) != ( - (xmin is not None and xmax is not None) - or (tmin is not None and tmax is not None) - ), ( - "Either string must be not None or at least a bound pair (xmin/max or " - "tmin/max) must be not None" - ) + (xmin is not None and xmax is not None) or (tmin is not None and tmax is not None) + ), "Either string must be not None or at least a bound pair (xmin/max or tmin/max) must be not None" if _inner is not None: self._inner = _inner elif string is not None: @@ -87,9 +81,7 @@ def __init__( else: span = floatspan_make(float(xmin), float(xmax), xmin_inc, xmax_inc) if tmin is not None and tmax is not None: - tstzspan = TsTzSpan( - lower=tmin, upper=tmax, lower_inc=tmin_inc, upper_inc=tmax_inc - )._inner + tstzspan = TsTzSpan(lower=tmin, upper=tmax, lower_inc=tmin_inc, upper_inc=tmax_inc)._inner self._inner = tbox_make(span, tstzspan) def __copy__(self) -> TBox: @@ -140,7 +132,7 @@ def from_hexwkb(hexwkb: str) -> TBox: return TBox(_inner=result) @staticmethod - def from_value(value: Union[int, float, IntSpan, FloatSpan]) -> TBox: + def from_value(value: int | float | IntSpan | FloatSpan) -> TBox: """ Returns a `TBox` from a numeric value or span. The created `TBox` will only have a numerical dimension. @@ -158,9 +150,7 @@ def from_value(value: Union[int, float, IntSpan, FloatSpan]) -> TBox: result = int_to_tbox(value) elif isinstance(value, float): result = float_to_tbox(value) - elif isinstance(value, IntSpan): - result = span_to_tbox(value._inner) - elif isinstance(value, FloatSpan): + elif isinstance(value, (IntSpan, FloatSpan)): result = span_to_tbox(value._inner) else: raise TypeError(f"Operation not supported with type {value.__class__}") @@ -195,9 +185,7 @@ def from_time(time: Time) -> TBox: return TBox(_inner=result) @staticmethod - def from_value_time( - value: Union[int, float, IntSpan, FloatSpan], time: Union[datetime, TsTzSpan] - ) -> TBox: + def from_value_time(value: int | float | IntSpan | FloatSpan, time: datetime | TsTzSpan) -> TBox: """ Returns a `TBox` from a numerical and a temporal object. @@ -222,21 +210,15 @@ def from_value_time( elif isinstance(value, float) and isinstance(time, TsTzSpan): result = float_tstzspan_to_tbox(value, time._inner) elif isinstance(value, IntSpan) and isinstance(time, datetime): - result = numspan_timestamptz_to_tbox( - value._inner, datetime_to_timestamptz(time) - ) + result = numspan_timestamptz_to_tbox(value._inner, datetime_to_timestamptz(time)) elif isinstance(value, IntSpan) and isinstance(time, TsTzSpan): result = numspan_tstzspan_to_tbox(value._inner, time._inner) elif isinstance(value, FloatSpan) and isinstance(time, datetime): - result = numspan_timestamptz_to_tbox( - value._inner, datetime_to_timestamptz(time) - ) + result = numspan_timestamptz_to_tbox(value._inner, datetime_to_timestamptz(time)) elif isinstance(value, FloatSpan) and isinstance(time, TsTzSpan): result = numspan_tstzspan_to_tbox(value._inner, time._inner) else: - raise TypeError( - f"Operation not supported with types {value.__class__} and {time.__class__}" - ) + raise TypeError(f"Operation not supported with types {value.__class__} and {time.__class__}") return TBox(_inner=result) @staticmethod @@ -278,7 +260,7 @@ def __repr__(self): MEOS Functions: tbox_out """ - return f"{self.__class__.__name__}" f"({self})" + return f"{self.__class__.__name__}({self})" def as_wkb(self) -> bytes: """ @@ -462,7 +444,7 @@ def tmax_inc(self) -> bool: return tbox_tmax_inc(self._inner) # ------------------------- Transformation -------------------------------- - def expand(self, other: Union[int, float, timedelta]) -> TBox: + def expand(self, other: int | float | timedelta) -> TBox: """ Returns the result of expanding ``self`` with the ``other``. Depending on the type of ``other``, the expansion will be of the numeric @@ -477,7 +459,7 @@ def expand(self, other: Union[int, float, timedelta]) -> TBox: MEOS Functions: tbox_expand_value, tbox_expand_time """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): if self._is_float(): result = tbox_expand_float(self._inner, float(other)) else: @@ -488,7 +470,7 @@ def expand(self, other: Union[int, float, timedelta]) -> TBox: raise TypeError(f"Operation not supported with type {other.__class__}") return TBox(_inner=result) - def shift_value(self, delta: Union[int, float]) -> TBox: + def shift_value(self, delta: int | float) -> TBox: """ Returns a new `TBox` with the value dimension shifted by `delta`. @@ -524,7 +506,7 @@ def shift_time(self, delta: timedelta) -> TBox: """ return self.shift_scale_time(shift=delta) - def scale_value(self, width: Union[int, float]) -> TBox: + def scale_value(self, width: int | float) -> TBox: """ Returns a new `TBox` with the value dimension having width `width`. @@ -562,8 +544,8 @@ def scale_time(self, duration: timedelta) -> TBox: def shift_scale_value( self, - shift: Optional[Union[int, float]] = None, - width: Optional[Union[int, float]] = None, + shift: int | float | None = None, + width: int | float | None = None, ) -> TBox: """ Returns a new TBox with the value span shifted by `shift` and @@ -587,14 +569,10 @@ def shift_scale_value( See Also: :meth:`Span.shift_scale` """ - assert ( - shift is not None or width is not None - ), "shift and width deltas must not be both None" + assert shift is not None or width is not None, "shift and width deltas must not be both None" hasshift = shift is not None haswidth = width is not None - if (shift is None or isinstance(shift, int)) and ( - width is None or isinstance(width, int) - ): + if (shift is None or isinstance(shift, int)) and (width is None or isinstance(width, int)): result = tbox_shift_scale_int( self._inner, shift if shift else 0, @@ -602,9 +580,7 @@ def shift_scale_value( hasshift, haswidth, ) - elif (shift is None or isinstance(shift, float)) and ( - width is None or isinstance(width, float) - ): + elif (shift is None or isinstance(shift, float)) and (width is None or isinstance(width, float)): result = tbox_shift_scale_float( self._inner, shift if shift else 0.0, @@ -616,9 +592,7 @@ def shift_scale_value( raise TypeError(f"Operation not supported with type {self.__class__}") return TBox(_inner=result) - def shift_scale_time( - self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None - ) -> TBox: + def shift_scale_time(self, shift: timedelta | None = None, duration: timedelta | None = None) -> TBox: """ Returns a new TBox with the temporal span shifted by `shift` and duration `duration`. @@ -643,9 +617,7 @@ def shift_scale_time( See Also: :meth:`TsTzSpan.shift_scale` """ - assert ( - shift is not None or duration is not None - ), "shift and duration deltas must not be both None" + assert shift is not None or duration is not None, "shift and duration deltas must not be both None" result = tbox_shift_scale_time( self._inner, timedelta_to_interval(shift) if shift else None, @@ -671,7 +643,7 @@ def round(self, max_decimals: int = 0) -> TBox: return TBox(_inner=tbox_round(self._inner, max_decimals)) # ------------------------- Set Operations -------------------------------- - def union(self, other: TBox, strict: Optional[bool] = True) -> TBox: + def union(self, other: TBox, strict: bool | None = True) -> TBox: """ Returns the union of `self` with `other`. @@ -704,7 +676,7 @@ def __add__(self, other): return self.union(other, False) # TODO: Check returning None for empty intersection is the desired behaviour - def intersection(self, other: TBox) -> Optional[TBox]: + def intersection(self, other: TBox) -> TBox | None: """ Returns the intersection of `self` with `other`. @@ -738,9 +710,7 @@ def __mul__(self, other): return self.intersection(other) # ------------------------- Topological Operations ------------------------ - def is_adjacent( - self, other: Union[int, float, IntSpan, FloatSpan, TBox, TNumber] - ) -> bool: + def is_adjacent(self, other: int | float | IntSpan | FloatSpan | TBox | TNumber) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share only the temporal or numerical bound and only one of them contains it. @@ -779,7 +749,7 @@ def is_adjacent( else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_contained_in(self, container: Union[TBox, TNumber]) -> bool: + def is_contained_in(self, container: TBox | TNumber) -> bool: """ Returns whether ``self`` is contained in ``container``. @@ -807,7 +777,7 @@ def is_contained_in(self, container: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {container.__class__}") - def contains(self, content: Union[TBox, TNumber]) -> bool: + def contains(self, content: TBox | TNumber) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -858,7 +828,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps(self, other: Union[TBox, TNumber]) -> bool: + def overlaps(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` overlaps ``other``. That is, both share at least an instant or a value. @@ -879,7 +849,7 @@ def overlaps(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_same(self, other: Union[TBox, TNumber]) -> bool: + def is_same(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is the same as ``other``. @@ -901,7 +871,7 @@ def is_same(self, other: Union[TBox, TNumber]) -> bool: raise TypeError(f"Operation not supported with type {other.__class__}") # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[TBox, TNumber]) -> bool: + def is_left(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is strictly to the left of ``other``. @@ -921,7 +891,7 @@ def is_left(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_over_or_left(self, other: Union[TBox, TNumber]) -> bool: + def is_over_or_left(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is to the left of ``other`` allowing overlap. That is, ``self`` does not extend to the right of ``other``. @@ -942,7 +912,7 @@ def is_over_or_left(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_right(self, other: Union[TBox, TNumber]) -> bool: + def is_right(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is strictly to the right of ``other``. @@ -962,7 +932,7 @@ def is_right(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_over_or_right(self, other: Union[TBox, TNumber]) -> bool: + def is_over_or_right(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is to the right of ``other`` allowing overlap. That is, ``self`` does not extend to the left of ``other``. @@ -983,7 +953,7 @@ def is_over_or_right(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_before(self, other: Union[TBox, TNumber]) -> bool: + def is_before(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is strictly before ``other``. @@ -1003,7 +973,7 @@ def is_before(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_over_or_before(self, other: Union[TBox, TNumber]) -> bool: + def is_over_or_before(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` does not extend after ``other``. @@ -1024,7 +994,7 @@ def is_over_or_before(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_after(self, other: Union[TBox, TNumber]) -> bool: + def is_after(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is strictly after ``other``. @@ -1044,7 +1014,7 @@ def is_after(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f"Operation not supported with type {other.__class__}") - def is_over_or_after(self, other: Union[TBox, TNumber]) -> bool: + def is_over_or_after(self, other: TBox | TNumber) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` does not extend before``other``. @@ -1066,7 +1036,7 @@ def is_over_or_after(self, other: Union[TBox, TNumber]) -> bool: raise TypeError(f"Operation not supported with type {other.__class__}") # ------------------------- Distance Operations --------------------------- - def nearest_approach_distance(self, other: Union[TBox, TNumber]) -> float: + def nearest_approach_distance(self, other: TBox | TNumber) -> float: """ Returns the distance between the nearest points of ``self`` and ``other``. @@ -1096,10 +1066,10 @@ def nearest_approach_distance(self, other: Union[TBox, TNumber]) -> float: def tile( self, size: float, - duration: Union[timedelta, str], + duration: timedelta | str, origin: float = 0.0, - start: Union[datetime, str, None] = None, - ) -> List[TBox]: + start: datetime | str | None = None, + ) -> list[TBox]: """ Returns a list of TBoxes resulting from tiling ``self``. @@ -1116,26 +1086,16 @@ def tile( MEOS Functions: tintbox_tile_list, tfloabox_tile_list """ - dt = ( - timedelta_to_interval(duration) - if isinstance(duration, timedelta) - else pg_interval_in(duration, -1) - ) + dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) else pg_interval_in(duration, -1) st = ( datetime_to_timestamptz(start) if isinstance(start, datetime) - else ( - pg_timestamptz_in(start, -1) - if isinstance(start, str) - else pg_timestamptz_in("2000-01-03", -1) - ) + else (pg_timestamptz_in(start, -1) if isinstance(start, str) else pg_timestamptz_in("2000-01-03", -1)) ) if self._is_float(): tiles, count = tfloatbox_value_time_tiles(self._inner, size, dt, origin, st) else: - tiles, count = tintbox_value_time_tiles( - self._inner, int(size), dt, int(origin), st - ) + tiles, count = tintbox_value_time_tiles(self._inner, int(size), dt, int(origin), st) return [TBox(_inner=tiles + c) for c in range(count)] # ------------------------- Comparisons ----------------------------------- diff --git a/pymeos/collections/__init__.py b/pymeos/collections/__init__.py index 23a0bd61..a741bad8 100644 --- a/pymeos/collections/__init__.py +++ b/pymeos/collections/__init__.py @@ -1,9 +1,8 @@ from .base import * +from .geo import * from .number import * from .text import * from .time import * -from .text import * -from .geo import * __all__ = [ "Set", diff --git a/pymeos/collections/base/collection.py b/pymeos/collections/base/collection.py index b0960748..419e96dc 100644 --- a/pymeos/collections/base/collection.py +++ b/pymeos/collections/base/collection.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Generic, TypeVar, Type +from typing import Generic, TypeVar T = TypeVar("T") Self = TypeVar("Self") @@ -50,7 +50,7 @@ def is_right(self, other) -> bool: # ------------------------- Database Operations --------------------------- @classmethod - def read_from_cursor(cls: Type[Self], value, _=None): + def read_from_cursor(cls: type[Self], value, _=None): """ Reads a :class:`Collection` from a database cursor. Used when automatically loading objects from the database. diff --git a/pymeos/collections/base/set.py b/pymeos/collections/base/set.py index c0b4163d..50391327 100644 --- a/pymeos/collections/base/set.py +++ b/pymeos/collections/base/set.py @@ -1,19 +1,18 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Optional, Union, List, overload -from typing import TypeVar, Type, Callable, Any, TYPE_CHECKING, Iterable +from collections.abc import Callable, Iterable +from typing import TYPE_CHECKING, Any, TypeVar, overload from pymeos_cffi import * from .collection import Collection if TYPE_CHECKING: - from .spanset import SpanSet - from .span import Span - - from ..number import IntSet, IntSpan, IntSpanSet, FloatSet, FloatSpan, FloatSpanSet + from ..number import FloatSet, FloatSpan, FloatSpanSet, IntSet, IntSpan, IntSpanSet from ..time import DateSet, DateSpan, DateSpanSet, TsTzSet, TsTzSpan, TsTzSpanSet + from .span import Span + from .spanset import SpanSet T = TypeVar("T") Self = TypeVar("Self", bound="Set[Any]") @@ -26,30 +25,28 @@ class Set(Collection[T], ABC): __slots__ = ["_inner"] - _parse_function: Callable[[str], "CData"] = None - _parse_value_function: Callable[[Union[str, T]], Any] = None - _make_function: Callable[[Iterable[Any]], "CData"] = None + _parse_function: Callable[[str], CData] = None + _parse_value_function: Callable[[str | T], Any] = None + _make_function: Callable[[Iterable[Any]], CData] = None # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - elements: Optional[List[Union[str, T]]] = None, + elements: list[str | T] | None = None, _inner=None, ): super().__init__() - assert (_inner is not None) or ( - (string is not None) != (elements is not None) - ), "Either string must be not None or elements must be not" + assert (_inner is not None) or ((string is not None) != (elements is not None)), ( + "Either string must be not None or elements must be not" + ) if _inner is not None: self._inner = _inner elif string is not None: self._inner = self.__class__._parse_function(string) else: - parsed_elements = [ - self.__class__._parse_value_function(ts) for ts in elements - ] + parsed_elements = [self.__class__._parse_value_function(ts) for ts in elements] self._inner = self.__class__._make_function(parsed_elements) def __copy__(self: Self) -> Self: @@ -66,7 +63,7 @@ def __copy__(self: Self) -> Self: return self.__class__(_inner=inner_copy) @classmethod - def from_wkb(cls: Type[Self], wkb: bytes) -> Self: + def from_wkb(cls: type[Self], wkb: bytes) -> Self: """ Returns a `Set` from its WKB representation. Args: @@ -83,7 +80,7 @@ def from_wkb(cls: Type[Self], wkb: bytes) -> Self: return _CollectionFactory.create_collection(set_from_wkb(wkb)) @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: + def from_hexwkb(cls: type[Self], hexwkb: str) -> Self: """ Returns a `Set` from its WKB representation in hex-encoded ASCII. Args: @@ -97,7 +94,7 @@ def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: """ from ...factory import _CollectionFactory - return _CollectionFactory.create_collection((set_from_hexwkb(hexwkb))) + return _CollectionFactory.create_collection(set_from_hexwkb(hexwkb)) # ------------------------- Output ---------------------------------------- @abstractmethod @@ -120,7 +117,7 @@ def __repr__(self) -> str: MEOS Functions: set_out """ - return f"{self.__class__.__name__}" f"({self})" + return f"{self.__class__.__name__}({self})" def as_wkb(self) -> bytes: """ @@ -146,16 +143,16 @@ def as_hexwkb(self) -> str: # ------------------------- Conversions ----------------------------------- @overload - def to_span(self: Type[IntSet]) -> IntSpan: ... + def to_span(self: type[IntSet]) -> IntSpan: ... @overload - def to_span(self: Type[FloatSet]) -> FloatSpan: ... + def to_span(self: type[FloatSet]) -> FloatSpan: ... @overload - def to_span(self: Type[TsTzSet]) -> TsTzSpan: ... + def to_span(self: type[TsTzSet]) -> TsTzSpan: ... @overload - def to_span(self: Type[DateSet]) -> DateSpan: ... + def to_span(self: type[DateSet]) -> DateSpan: ... def to_span(self) -> Span: """ @@ -172,16 +169,16 @@ def to_span(self) -> Span: return _CollectionFactory.create_collection(set_span(self._inner)) @overload - def to_spanset(self: Type[IntSet]) -> IntSpanSet: ... + def to_spanset(self: type[IntSet]) -> IntSpanSet: ... @overload - def to_spanset(self: Type[FloatSet]) -> FloatSpanSet: ... + def to_spanset(self: type[FloatSet]) -> FloatSpanSet: ... @overload - def to_spanset(self: Type[TsTzSet]) -> TsTzSpanSet: ... + def to_spanset(self: type[TsTzSet]) -> TsTzSpanSet: ... @overload - def to_spanset(self: Type[DateSet]) -> DateSpanSet: ... + def to_spanset(self: type[DateSet]) -> DateSpanSet: ... def to_spanset(self) -> SpanSet: """ @@ -250,7 +247,7 @@ def element_n(self, n: int) -> T: raise IndexError(f"Index {n} out of bounds") @abstractmethod - def elements(self) -> List[T]: + def elements(self) -> list[T]: """ Returns the list of distinct elements in ``self``. Returns: diff --git a/pymeos/collections/base/span.py b/pymeos/collections/base/span.py index 42b6cc7f..23f1cbb4 100644 --- a/pymeos/collections/base/span.py +++ b/pymeos/collections/base/span.py @@ -1,8 +1,8 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Optional, Union -from typing import TypeVar, Type, Callable, Any, TYPE_CHECKING +from collections.abc import Callable +from typing import TYPE_CHECKING, Any, TypeVar from pymeos_cffi import * @@ -22,25 +22,25 @@ class Span(Collection[T], ABC): __slots__ = ["_inner"] - _parse_function: Callable[[str], "CData"] = None - _parse_value_function: Callable[[Union[str, T]], Any] = None - _make_function: Callable[[Any, Any, bool, bool], "CData"] = None + _parse_function: Callable[[str], CData] = None + _parse_value_function: Callable[[str | T], Any] = None + _make_function: Callable[[Any, Any, bool, bool], CData] = None # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - lower: Optional[Union[str, T]] = None, - upper: Optional[Union[str, T]] = None, - lower_inc: Optional[bool] = True, - upper_inc: Optional[bool] = False, + lower: str | T | None = None, + upper: str | T | None = None, + lower_inc: bool | None = True, + upper_inc: bool | None = False, _inner=None, ): super().__init__() - assert (_inner is not None) or ( - (string is not None) != (lower is not None and upper is not None) - ), "Either string must be not None or both lower and upper must be not" + assert (_inner is not None) or ((string is not None) != (lower is not None and upper is not None)), ( + "Either string must be not None or both lower and upper must be not" + ) if _inner is not None: self._inner = _inner elif string is not None: @@ -48,9 +48,7 @@ def __init__( else: lower_converted = self.__class__._parse_value_function(lower) upper_converted = self.__class__._parse_value_function(upper) - self._inner = self.__class__._make_function( - lower_converted, upper_converted, lower_inc, upper_inc - ) + self._inner = self.__class__._make_function(lower_converted, upper_converted, lower_inc, upper_inc) def __copy__(self: Self) -> Self: """ @@ -66,7 +64,7 @@ def __copy__(self: Self) -> Self: return self.__class__(_inner=inner_copy) @classmethod - def from_wkb(cls: Type[Self], wkb: bytes) -> Self: + def from_wkb(cls: type[Self], wkb: bytes) -> Self: """ Returns a `TsTzSpan` from its WKB representation. @@ -82,7 +80,7 @@ def from_wkb(cls: Type[Self], wkb: bytes) -> Self: return cls(_inner=(span_from_wkb(wkb))) @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: + def from_hexwkb(cls: type[Self], hexwkb: str) -> Self: """ Returns a `TsTzSpan` from its WKB representation in hex-encoded ASCII. @@ -116,7 +114,7 @@ def __repr__(self): Returns: A new :class:`str` instance """ - return f"{self.__class__.__name__}" f"({self})" + return f"{self.__class__.__name__}({self})" def as_wkb(self) -> bytes: """ diff --git a/pymeos/collections/base/spanset.py b/pymeos/collections/base/spanset.py index d4ce7a45..232fb5f3 100644 --- a/pymeos/collections/base/spanset.py +++ b/pymeos/collections/base/spanset.py @@ -1,8 +1,8 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Optional, Union -from typing import TypeVar, Type, Callable, Any, TYPE_CHECKING, List +from collections.abc import Callable +from typing import TYPE_CHECKING, Any, TypeVar from pymeos_cffi import * @@ -22,29 +22,29 @@ class SpanSet(Collection[T], ABC): __slots__ = ["_inner"] - _parse_function: Callable[[str], "CData"] = None - _parse_value_function: Callable[[Union[str, T]], Any] = None + _parse_function: Callable[[str], CData] = None + _parse_value_function: Callable[[str | T], Any] = None # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - span_list: Optional[List[Union[str, Span]]] = None, + span_list: list[str | Span] | None = None, normalize: bool = True, _inner=None, ): super().__init__() - assert (_inner is not None) or ( - (string is not None) != (span_list is not None) - ), "Either string must be not None or span_list must be not" + assert (_inner is not None) or ((string is not None) != (span_list is not None)), ( + "Either string must be not None or span_list must be not" + ) if _inner is not None: self._inner = _inner elif string is not None: self._inner = self.__class__._parse_function(string) else: spans = [self.__class__._parse_value_function(p) for p in span_list] - self._inner = spanset_make(spans, normalize, True) + self._inner = spanset_make(spans) def __copy__(self: Self) -> Self: """ @@ -60,7 +60,7 @@ def __copy__(self: Self) -> Self: return self.__class__(_inner=inner_copy) @classmethod - def from_wkb(cls: Type[Self], wkb: bytes) -> Self: + def from_wkb(cls: type[Self], wkb: bytes) -> Self: """ Returns a `SpanSet` from its WKB representation. @@ -77,7 +77,7 @@ def from_wkb(cls: Type[Self], wkb: bytes) -> Self: return cls(_inner=result) @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: + def from_hexwkb(cls: type[Self], hexwkb: str) -> Self: """ Returns a `SpanSet` from its WKB representation in hex-encoded ASCII. Args: @@ -113,7 +113,7 @@ def __repr__(self): MEOS Functions: tstzspanset_out """ - return f"{self.__class__.__name__}" f"({self})" + return f"{self.__class__.__name__}({self})" def as_wkb(self) -> bytes: """ @@ -202,7 +202,7 @@ def span_n(self, n: int) -> Span: return spanset_span_n(self._inner, n + 1) @abstractmethod - def spans(self) -> List[Span]: + def spans(self) -> list[Span]: """ Returns the list of tstzspans in ``self``. Returns: diff --git a/pymeos/collections/geo/__init__.py b/pymeos/collections/geo/__init__.py index c53cefa1..c2476061 100644 --- a/pymeos/collections/geo/__init__.py +++ b/pymeos/collections/geo/__init__.py @@ -1,3 +1,3 @@ -from .geoset import GeoSet, GeometrySet, GeographySet +from .geoset import GeographySet, GeometrySet, GeoSet __all__ = ["GeoSet", "GeometrySet", "GeographySet"] diff --git a/pymeos/collections/geo/geoset.py b/pymeos/collections/geo/geoset.py index 043a69ed..80e18468 100644 --- a/pymeos/collections/geo/geoset.py +++ b/pymeos/collections/geo/geoset.py @@ -1,33 +1,32 @@ from __future__ import annotations from abc import ABC -from typing import List, overload, Optional, Union, TypeVar +from typing import TypeVar, overload import shapely as shp from pymeos_cffi import ( - geoset_start_value, - gserialized_to_shapely_geometry, + geog_in, + geography_to_gserialized, + geogset_in, + geom_in, + geometry_to_gserialized, + geomset_in, geoset_end_value, + geoset_make, + geoset_start_value, geoset_value_n, geoset_values, + gserialized_to_shapely_geometry, intersection_set_geo, - minus_set_geo, - union_set_geo, - geoset_as_ewkt, - geoset_as_text, - geoset_out, - geoset_make, - geoset_srid, - geoset_round, - minus_geo_set, - geomset_in, - geogset_in, - pgis_geometry_in, - geometry_to_gserialized, - pgis_geography_in, - geography_to_gserialized, intersection_set_set, + minus_geo_set, + minus_set_geo, minus_set_set, + set_round, + spatialset_as_ewkt, + spatialset_as_text, + spatialset_srid, + union_set_geo, union_set_set, ) @@ -53,9 +52,9 @@ def __str__(self, max_decimals: int = 15): A new :class:`str` instance MEOS Functions: - geoset_out + spatialset_as_text """ - return geoset_out(self._inner, max_decimals) + return self.as_text(max_decimals) def as_ewkt(self, max_decimals: int = 15) -> str: """ @@ -68,9 +67,9 @@ def as_ewkt(self, max_decimals: int = 15) -> str: A :class:`str` instance. MEOS Functions: - geoset_as_ewkt + spatialset_as_ewkt """ - return geoset_as_ewkt(self._inner, max_decimals) + return spatialset_as_ewkt(self._inner, max_decimals) def as_wkt(self, max_decimals: int = 15): """ @@ -83,9 +82,9 @@ def as_wkt(self, max_decimals: int = 15): A :class:`str` instance. MEOS Functions: - geoset_as_text + spatialset_as_text """ - return geoset_as_text(self._inner, max_decimals) + return spatialset_as_text(self._inner, max_decimals) def as_text(self, max_decimals: int = 15): """ @@ -98,9 +97,9 @@ def as_text(self, max_decimals: int = 15): A :class:`str` instance. MEOS Functions: - geoset_as_text + spatialset_as_text """ - return geoset_as_text(self._inner, max_decimals) + return spatialset_as_text(self._inner, max_decimals) # ------------------------- Conversions ----------------------------------- @@ -152,7 +151,7 @@ def element_n(self, n: int) -> shp.Geometry: super().element_n(n) return gserialized_to_shapely_geometry(geoset_value_n(self._inner, n + 1)[0]) - def elements(self) -> List[shp.Geometry]: + def elements(self) -> list[shp.Geometry]: """ Returns a list of all elements in ``self``. @@ -163,10 +162,7 @@ def elements(self) -> List[shp.Geometry]: geoset_values """ elems = geoset_values(self._inner) - return [ - gserialized_to_shapely_geometry(elems[i]) - for i in range(self.num_elements()) - ] + return [gserialized_to_shapely_geometry(elems[i]) for i in range(self.num_elements())] def srid(self) -> int: """ @@ -176,13 +172,13 @@ def srid(self) -> int: An integer MEOS Functions: - geoset_srid + spatialset_srid """ - return geoset_srid(self._inner) + return spatialset_srid(self._inner) # ------------------------- Topological Operations -------------------------------- - def contains(self, content: Union[GeoSet, str]) -> bool: + def contains(self, content: GeoSet | str) -> bool: """ Returns whether ``self`` contains ``content``. @@ -197,10 +193,10 @@ def contains(self, content: Union[GeoSet, str]) -> bool: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: shp.Geometry) -> Optional[shp.Geometry]: ... + def intersection(self, other: shp.Geometry) -> shp.Geometry | None: ... @overload - def intersection(self, other: GeoSet) -> Optional[GeoSet]: ... + def intersection(self, other: GeoSet) -> GeoSet | None: ... def intersection(self, other): """ @@ -216,16 +212,14 @@ def intersection(self, other): intersection_set_geo, intersection_set_set """ if isinstance(other, shp.Geometry): - return gserialized_to_shapely_geometry( - intersection_set_geo(self._inner, geometry_to_gserialized(other))[0] - ) + return gserialized_to_shapely_geometry(intersection_set_geo(self._inner, geometry_to_gserialized(other))[0]) elif isinstance(other, GeoSet): result = intersection_set_set(self._inner, other._inner) return GeoSet(_inner=result) if result is not None else None else: return super().intersection(other) - def minus(self, other: Union[GeoSet, shp.Geometry]) -> Optional[GeoSet]: + def minus(self, other: GeoSet | shp.Geometry) -> GeoSet | None: """ Returns the difference of ``self`` and ``other``. @@ -250,7 +244,7 @@ def minus(self, other: Union[GeoSet, shp.Geometry]) -> Optional[GeoSet]: else: return super().minus(other) - def subtract_from(self, other: shp.Geometry) -> Optional[shp.Geometry]: + def subtract_from(self, other: shp.Geometry) -> shp.Geometry | None: """ Returns the difference of ``other`` and ``self``. @@ -267,11 +261,9 @@ def subtract_from(self, other: shp.Geometry) -> Optional[shp.Geometry]: :meth:`minus` """ result = minus_geo_set(geometry_to_gserialized(other), self._inner) - return ( - gserialized_to_shapely_geometry(result[0]) if result is not None else None - ) + return gserialized_to_shapely_geometry(result[0]) if result is not None else None - def union(self, other: Union[GeoSet, shp.Geometry]) -> GeoSet: + def union(self, other: GeoSet | shp.Geometry) -> GeoSet: """ Returns the union of ``self`` and ``other``. @@ -308,22 +300,18 @@ def round(self: Self, max_decimals: int) -> Self: MEOS Functions: tpoint_roundgeoset_round """ - return self.__class__(_inner=geoset_round(self._inner, max_decimals)) + return self.__class__(_inner=set_round(self._inner, max_decimals)) class GeometrySet(GeoSet): _mobilitydb_name = "geomset" _parse_function = geomset_in - _parse_value_function = lambda x: ( - pgis_geometry_in(x, -1) if isinstance(x, str) else geometry_to_gserialized(x) - ) + _parse_value_function = lambda x: (geom_in(x, -1) if isinstance(x, str) else geometry_to_gserialized(x)) class GeographySet(GeoSet): _mobilitydb_name = "geogset" _parse_function = geogset_in - _parse_value_function = lambda x: ( - pgis_geography_in(x, -1) if isinstance(x, str) else geography_to_gserialized(x) - ) + _parse_value_function = lambda x: (geog_in(x, -1) if isinstance(x, str) else geography_to_gserialized(x)) diff --git a/pymeos/collections/number/__init__.py b/pymeos/collections/number/__init__.py index b2839db0..6b73300c 100644 --- a/pymeos/collections/number/__init__.py +++ b/pymeos/collections/number/__init__.py @@ -1,8 +1,8 @@ -from .intset import IntSet -from .intspan import IntSpan -from .intspanset import IntSpanSet from .floatset import FloatSet from .floatspan import FloatSpan from .floatspanset import FloatSpanSet +from .intset import IntSet +from .intspan import IntSpan +from .intspanset import IntSpanSet __all__ = ["IntSet", "IntSpan", "IntSpanSet", "FloatSet", "FloatSpan", "FloatSpanSet"] diff --git a/pymeos/collections/number/floatset.py b/pymeos/collections/number/floatset.py index 000241e8..f1332d30 100644 --- a/pymeos/collections/number/floatset.py +++ b/pymeos/collections/number/floatset.py @@ -1,35 +1,35 @@ from __future__ import annotations -from typing import List, Union, overload, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, overload from pymeos_cffi import ( + contains_set_float, + distance_floatset_floatset, + distance_set_float, + floatset_end_value, floatset_in, floatset_make, floatset_out, + floatset_shift_scale, floatset_start_value, - floatset_end_value, floatset_value_n, floatset_values, - contains_set_float, intersection_set_float, intersection_set_set, left_set_float, - overleft_set_float, - right_set_float, - overright_set_float, + minus_float_set, minus_set_float, minus_set_set, - union_set_set, + overleft_set_float, + overright_set_float, + right_set_float, union_set_float, - floatset_shift_scale, - minus_float_set, - distance_set_float, - distance_floatset_floatset, + union_set_set, ) +from ..base import Set from .floatspan import FloatSpan from .floatspanset import FloatSpanSet -from ..base import Set if TYPE_CHECKING: from .intset import IntSet @@ -131,7 +131,7 @@ def element_n(self, n: int) -> float: super().element_n(n) return floatset_value_n(self._inner, n + 1) - def elements(self) -> List[float]: + def elements(self) -> list[float]: """ Returns the elements in ``self``. @@ -177,9 +177,7 @@ def scale(self, new_width: float) -> FloatSet: """ return self.shift_scale(None, new_width) - def shift_scale( - self, delta: Optional[float], new_width: Optional[float] - ) -> FloatSet: + def shift_scale(self, delta: float | None, new_width: float | None) -> FloatSet: """ Returns a new ``FloatSet`` instance with all elements shifted by ``delta`` and scaled to so that the encompassing span has width ``new_width``. @@ -195,14 +193,12 @@ def shift_scale( floatset_shift_scale """ return FloatSet( - _inner=floatset_shift_scale( - self._inner, delta, new_width, delta is not None, new_width is not None - ) + _inner=floatset_shift_scale(self._inner, delta, new_width, delta is not None, new_width is not None) ) # ------------------------- Topological Operations -------------------------------- - def contains(self, content: Union[FloatSet, float]) -> bool: + def contains(self, content: FloatSet | float) -> bool: """ Returns whether ``self`` contains ``content``. @@ -222,7 +218,7 @@ def contains(self, content: Union[FloatSet, float]) -> bool: # ------------------------- Position Operations -------------------------------- - def is_left(self, content: Union[FloatSet, float]) -> bool: + def is_left(self, content: FloatSet | float) -> bool: """ Returns whether ``self`` is strictly to the left of ``other``. That is, ``self`` ends before ``other`` starts. @@ -241,7 +237,7 @@ def is_left(self, content: Union[FloatSet, float]) -> bool: else: return super().is_left(content) - def is_over_or_left(self, content: Union[FloatSet, float]) -> bool: + def is_over_or_left(self, content: FloatSet | float) -> bool: """ Returns whether ``self`` is to the left of ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same value). @@ -260,7 +256,7 @@ def is_over_or_left(self, content: Union[FloatSet, float]) -> bool: else: return super().is_over_or_left(content) - def is_right(self, content: Union[FloatSet, float]) -> bool: + def is_right(self, content: FloatSet | float) -> bool: """ Returns whether ``self`` is strictly to the left of ``other``. That is, ``self`` starts before ``other`` ends. @@ -279,7 +275,7 @@ def is_right(self, content: Union[FloatSet, float]) -> bool: else: return super().is_right(content) - def is_over_or_right(self, content: Union[FloatSet, float]) -> bool: + def is_over_or_right(self, content: FloatSet | float) -> bool: """ Returns whether ``self`` is to the right of ``other`` allowing overlap. That is, ``self`` ends after ``other`` ends (or at the same value). @@ -301,10 +297,10 @@ def is_over_or_right(self, content: Union[FloatSet, float]) -> bool: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: float) -> Optional[float]: ... + def intersection(self, other: float) -> float | None: ... @overload - def intersection(self, other: FloatSet) -> Optional[FloatSet]: ... + def intersection(self, other: FloatSet) -> FloatSet | None: ... def intersection(self, other): """ @@ -327,7 +323,7 @@ def intersection(self, other): else: return super().intersection(other) - def minus(self, other: Union[FloatSet, float]) -> Optional[FloatSet]: + def minus(self, other: FloatSet | float) -> FloatSet | None: """ Returns the difference of ``self`` and ``other``. @@ -349,7 +345,7 @@ def minus(self, other: Union[FloatSet, float]) -> Optional[FloatSet]: else: return super().minus(other) - def subtract_from(self, other: float) -> Optional[float]: + def subtract_from(self, other: float) -> float | None: """ Returns the difference of ``other`` and ``self``. @@ -367,7 +363,7 @@ def subtract_from(self, other: float) -> Optional[float]: """ return minus_float_set(other, self._inner) - def union(self, other: Union[FloatSet, float]) -> FloatSet: + def union(self, other: FloatSet | float) -> FloatSet: """ Returns the union of ``self`` and ``other``. @@ -391,9 +387,7 @@ def union(self, other: Union[FloatSet, float]) -> FloatSet: # ------------------------- Distance Operations --------------------------- - def distance( - self, other: Union[int, float, FloatSet, FloatSpan, FloatSpanSet] - ) -> float: + def distance(self, other: int | float | FloatSet | FloatSpan | FloatSpanSet) -> float: """ Returns the distance between ``self`` and ``other``. @@ -416,9 +410,7 @@ def distance( return distance_set_float(self._inner, other) elif isinstance(other, FloatSet): return distance_floatset_floatset(self._inner, other._inner) - elif isinstance(other, FloatSpan): - return self.to_spanset().distance(other) - elif isinstance(other, FloatSpanSet): + elif isinstance(other, (FloatSpan, FloatSpanSet)): return self.to_spanset().distance(other) else: return super().distance(other) diff --git a/pymeos/collections/number/floatspan.py b/pymeos/collections/number/floatspan.py index c14f3241..0750e220 100644 --- a/pymeos/collections/number/floatspan.py +++ b/pymeos/collections/number/floatspan.py @@ -1,36 +1,36 @@ from __future__ import annotations -from typing import Union, overload, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, overload from pymeos_cffi import ( - intersection_span_float, + adjacent_span_float, + contains_span_float, + distance_floatspan_floatspan, + distance_floatspanset_floatspan, distance_span_float, + float_to_span, floatspan_in, floatspan_lower, - floatspan_upper, + floatspan_make, + floatspan_out, floatspan_shift_scale, - contains_span_float, - adjacent_span_float, - float_to_span, - span_eq, - left_span_float, - overleft_span_float, - right_span_float, - overright_span_float, + floatspan_to_intspan, + floatspan_upper, + floatspan_width, + intersection_span_float, intersection_span_span, intersection_spanset_span, + left_span_float, minus_span_float, minus_span_span, minus_spanset_span, + overleft_span_float, + overright_span_float, + right_span_float, + span_eq, union_span_float, union_span_span, union_spanset_span, - floatspan_out, - floatspan_make, - floatspan_width, - floatspan_to_intspan, - distance_floatspan_floatspan, - distance_floatspanset_floatspan, ) from ..base import Span @@ -183,7 +183,7 @@ def scale(self, width: float) -> FloatSpan: """ return self.shift_scale(None, width) - def shift_scale(self, delta: Optional[float], width: Optional[float]) -> FloatSpan: + def shift_scale(self, delta: float | None, width: float | None) -> FloatSpan: """ Return a new ``FloatSpan`` with the lower and upper bounds shifted by ``delta`` and scaled so that the width is ``width``. @@ -200,14 +200,12 @@ def shift_scale(self, delta: Optional[float], width: Optional[float]) -> FloatSp """ d = delta if delta is not None else 0 w = width if width is not None else 0 - modified = floatspan_shift_scale( - self._inner, d, w, delta is not None, width is not None - ) + modified = floatspan_shift_scale(self._inner, d, w, delta is not None, width is not None) return FloatSpan(_inner=modified) # ------------------------- Topological Operations -------------------------------- - def is_adjacent(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: + def is_adjacent(self, other: int | float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -221,12 +219,12 @@ def is_adjacent(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool MEOS Functions: adjacent_span_span, adjacent_span_spanset, adjacent_span_float """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return adjacent_span_float(self._inner, float(other)) else: return super().is_adjacent(other) - def contains(self, content: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: + def contains(self, content: int | float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` contains ``content``. @@ -239,12 +237,12 @@ def contains(self, content: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: MEOS Functions: contains_set_set, contains_span_float """ - if isinstance(content, int) or isinstance(content, float): + if isinstance(content, (int, float)): return contains_span_float(self._inner, float(content)) else: return super().contains(content) - def is_same(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: + def is_same(self, other: int | float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` and the bounding tstzspan of ``other`` is the same. @@ -258,13 +256,13 @@ def is_same(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: MEOS Functions: same_tstzspan_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return span_eq(self._inner, float_to_span(float(other))) else: return super().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: + def is_left(self, other: int | float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -278,14 +276,12 @@ def is_left(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: MEOS Functions: left_span_span, left_span_spanset, left_span_float """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return left_span_float(self._inner, float(other)) else: return super().is_left(other) - def is_over_or_left( - self, other: Union[int, float, FloatSpan, FloatSpanSet] - ) -> bool: + def is_over_or_left(self, other: int | float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same value). @@ -299,12 +295,12 @@ def is_over_or_left( MEOS Functions: overleft_span_span, overleft_span_spanset, overleft_span_float """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return overleft_span_float(self._inner, float(other)) else: return super().is_over_or_left(other) - def is_right(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: + def is_right(self, other: int | float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is strictly after ``other``. That is, ``self`` starts after ``other`` ends. @@ -318,12 +314,12 @@ def is_right(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> bool: MEOS Functions: right_span_span, right_span_spanset, right_span_float """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return right_span_float(self._inner, float(other)) else: return super().is_right(other) - def is_over_or_right(self, other: Union[float, FloatSpan, FloatSpanSet]) -> bool: + def is_over_or_right(self, other: float | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same value). @@ -337,15 +333,13 @@ def is_over_or_right(self, other: Union[float, FloatSpan, FloatSpanSet]) -> bool MEOS Functions: overright_span_span, overright_span_spanset, overright_span_float """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return overright_span_float(self._inner, float(other)) else: return super().is_over_or_right(other) # ------------------------- Distance Operations --------------------------- - def distance( - self, other: Union[int, float, FloatSet, FloatSpan, FloatSpanSet] - ) -> float: + def distance(self, other: int | float | FloatSet | FloatSpan | FloatSpanSet) -> float: """ Returns the distance between ``self`` and ``other``. @@ -377,13 +371,13 @@ def distance( # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: Union[int, float]) -> Optional[float]: ... + def intersection(self, other: int | float) -> float | None: ... @overload - def intersection(self, other: FloatSpan) -> Optional[FloatSpan]: ... + def intersection(self, other: FloatSpan) -> FloatSpan | None: ... @overload - def intersection(self, other: FloatSpanSet) -> Optional[FloatSpanSet]: ... + def intersection(self, other: FloatSpanSet) -> FloatSpanSet | None: ... def intersection(self, other): """ @@ -402,7 +396,7 @@ def intersection(self, other): """ from .floatspanset import FloatSpanSet - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): return intersection_span_float(self._inner, float(other)) elif isinstance(other, FloatSpan): result = intersection_span_span(self._inner, other._inner) @@ -413,7 +407,7 @@ def intersection(self, other): else: super().intersection(other) - def minus(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> FloatSpanSet: + def minus(self, other: int | float | FloatSpan | FloatSpanSet) -> FloatSpanSet: """ Returns the difference of ``self`` and ``other``. @@ -428,7 +422,7 @@ def minus(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> FloatSpanS """ from .floatspanset import FloatSpanSet - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = minus_span_float(self._inner, float(other)) elif isinstance(other, FloatSpan): result = minus_span_span(self._inner, other._inner) @@ -438,7 +432,7 @@ def minus(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> FloatSpanS result = super().minus(other) return FloatSpanSet(_inner=result) if result is not None else None - def union(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> FloatSpanSet: + def union(self, other: int | float | FloatSpan | FloatSpanSet) -> FloatSpanSet: """ Returns the union of ``self`` and ``other``. @@ -453,7 +447,7 @@ def union(self, other: Union[int, float, FloatSpan, FloatSpanSet]) -> FloatSpanS """ from .floatspanset import FloatSpanSet - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = union_span_float(self._inner, float(other)) elif isinstance(other, FloatSpan): result = union_span_span(self._inner, other._inner) diff --git a/pymeos/collections/number/floatspanset.py b/pymeos/collections/number/floatspanset.py index 98d18ee0..f93462f4 100644 --- a/pymeos/collections/number/floatspanset.py +++ b/pymeos/collections/number/floatspanset.py @@ -1,27 +1,27 @@ from __future__ import annotations -from typing import Union, overload, Optional, TYPE_CHECKING, List +from typing import TYPE_CHECKING, overload from pymeos_cffi import ( - floatspanset_in, - floatspanset_out, - floatspanset_width, - floatspanset_shift_scale, adjacent_spanset_float, contains_spanset_float, - spanset_eq, + distance_floatspanset_floatspan, + distance_floatspanset_floatspanset, + distance_spanset_float, float_to_spanset, + floatspanset_in, + floatspanset_out, + floatspanset_shift_scale, + floatspanset_to_intspanset, + floatspanset_width, + intersection_spanset_float, left_spanset_float, + minus_spanset_float, overleft_spanset_float, - right_spanset_float, overright_spanset_float, - distance_spanset_float, - intersection_spanset_float, + right_spanset_float, + spanset_eq, union_spanset_float, - minus_spanset_float, - floatspanset_to_intspanset, - distance_floatspanset_floatspan, - distance_floatspanset_floatspanset, ) from ..base import SpanSet @@ -55,9 +55,7 @@ class FloatSpanSet(SpanSet[float]): _mobilitydb_name = "floatspanset" _parse_function = floatspanset_in - _parse_value_function = lambda span: ( - floatspanset_in(span)[0] if isinstance(span, str) else span._inner[0] - ) + _parse_value_function = lambda span: (floatspanset_in(span)[0] if isinstance(span, str) else span._inner[0]) # ------------------------- Output ---------------------------------------- def __str__(self, max_decimals: int = 15): @@ -104,7 +102,7 @@ def to_intspanset(self) -> IntSpanSet: # ------------------------- Accessors ------------------------------------- - def width(self, ignore_gaps: Optional[bool] = False) -> float: + def width(self, ignore_gaps: bool | None = False) -> float: """ Returns the width of the spanset. By default, i.e., when the second argument is False, the function takes into account the gaps within, @@ -164,7 +162,7 @@ def span_n(self, n: int) -> FloatSpan: return FloatSpan(_inner=super().span_n(n)) - def spans(self) -> List[FloatSpan]: + def spans(self) -> list[FloatSpan]: """ Returns the list of spans in ``self``. Returns: @@ -212,7 +210,7 @@ def scale(self, width: int) -> FloatSpanSet: """ return self.shift_scale(None, width) - def shift_scale(self, delta: Optional[int], width: Optional[int]) -> FloatSpanSet: + def shift_scale(self, delta: int | None, width: int | None) -> FloatSpanSet: """ Return a new ``FloatSpanSet`` with the lower and upper bounds shifted by ``delta`` and scaled so that the width is ``width``. @@ -229,14 +227,12 @@ def shift_scale(self, delta: Optional[int], width: Optional[int]) -> FloatSpanSe """ d = delta if delta is not None else 0 w = width if width is not None else 0 - modified = floatspanset_shift_scale( - self._inner, d, w, delta is not None, width is not None - ) + modified = floatspanset_shift_scale(self._inner, d, w, delta is not None, width is not None) return FloatSpanSet(_inner=modified) # ------------------------- Topological Operations -------------------------------- - def is_adjacent(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def is_adjacent(self, other: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -256,7 +252,7 @@ def is_adjacent(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: else: return super().is_adjacent(other) - def contains(self, content: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def contains(self, content: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` contains ``content``. @@ -275,7 +271,7 @@ def contains(self, content: Union[int, FloatSpan, FloatSpanSet]) -> bool: else: return super().contains(content) - def is_same(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def is_same(self, other: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` and the bounding tstzspan of ``other`` is the same. @@ -295,7 +291,7 @@ def is_same(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: return super().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def is_left(self, other: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is strictly left of ``other``. That is, ``self`` ends before ``other`` starts. @@ -314,7 +310,7 @@ def is_left(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: else: return super().is_left(other) - def is_over_or_left(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def is_over_or_left(self, other: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is left ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same value). @@ -333,7 +329,7 @@ def is_over_or_left(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: else: return super().is_over_or_left(other) - def is_right(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def is_right(self, other: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is strictly right ``other``. That is, ``self`` starts after ``other`` ends. @@ -352,7 +348,7 @@ def is_right(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: else: return super().is_right(other) - def is_over_or_right(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: + def is_over_or_right(self, other: int | FloatSpan | FloatSpanSet) -> bool: """ Returns whether ``self`` is right ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same value). @@ -373,9 +369,7 @@ def is_over_or_right(self, other: Union[int, FloatSpan, FloatSpanSet]) -> bool: return super().is_over_or_right(other) # ------------------------- Distance Operations --------------------------- - def distance( - self, other: Union[int, float, FloatSet, FloatSpan, FloatSpanSet] - ) -> float: + def distance(self, other: int | float | FloatSet | FloatSpan | FloatSpanSet) -> float: """ Returns the distance between ``self`` and ``other``. @@ -408,13 +402,13 @@ def distance( # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: Union[int, float]) -> Optional[float]: ... + def intersection(self, other: int | float) -> float | None: ... @overload - def intersection(self, other: FloatSpan) -> Optional[FloatSpanSet]: ... + def intersection(self, other: FloatSpan) -> FloatSpanSet | None: ... @overload - def intersection(self, other: FloatSpanSet) -> Optional[FloatSpanSet]: ... + def intersection(self, other: FloatSpanSet) -> FloatSpanSet | None: ... def intersection(self, other): """ @@ -431,7 +425,7 @@ def intersection(self, other): intersection_spanset_float, intersection_spanset_spanset, intersection_spanset_span """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = intersection_spanset_float(self._inner, float(other)) else: result = super().intersection(other) @@ -453,7 +447,7 @@ def __mul__(self, other): """ return self.intersection(other) - def minus(self, other: Union[int, FloatSpan, FloatSpanSet]) -> FloatSpanSet: + def minus(self, other: int | FloatSpan | FloatSpanSet) -> FloatSpanSet: """ Returns the difference of ``self`` and ``other``. @@ -466,7 +460,7 @@ def minus(self, other: Union[int, FloatSpan, FloatSpanSet]) -> FloatSpanSet: MEOS Functions: minus_spanset_span, minus_spanset_spanset, minus_spanset_float """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = minus_spanset_float(self._inner, float(other)) else: result = super().minus(other) @@ -488,7 +482,7 @@ def __sub__(self, other): """ return self.minus(other) - def union(self, other: Union[int, FloatSpan, FloatSpanSet]) -> FloatSpanSet: + def union(self, other: int | FloatSpan | FloatSpanSet) -> FloatSpanSet: """ Returns the union of ``self`` and ``other``. @@ -502,7 +496,7 @@ def union(self, other: Union[int, FloatSpan, FloatSpanSet]) -> FloatSpanSet: union_spanset_float, union_spanset_spanset, union_spanset_span """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = union_spanset_float(self._inner, float(other)) else: result = super().union(other) diff --git a/pymeos/collections/number/intset.py b/pymeos/collections/number/intset.py index 0c20b377..a512c7d5 100644 --- a/pymeos/collections/number/intset.py +++ b/pymeos/collections/number/intset.py @@ -1,35 +1,35 @@ from __future__ import annotations -from typing import List, Union, overload, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, overload from pymeos_cffi import ( + contains_set_int, + distance_intset_intset, + distance_set_int, + intersection_set_int, + intersection_set_set, + intset_end_value, intset_in, intset_make, intset_out, + intset_shift_scale, intset_start_value, - intset_end_value, intset_value_n, intset_values, - contains_set_int, - intersection_set_int, - intersection_set_set, - minus_set_int, left_set_int, + minus_int_set, + minus_set_int, + minus_set_set, overleft_set_int, - right_set_int, overright_set_int, - minus_set_set, - union_set_set, + right_set_int, union_set_int, - intset_shift_scale, - minus_int_set, - distance_set_int, - distance_intset_intset, + union_set_set, ) +from ..base import Set from .intspan import IntSpan from .intspanset import IntSpanSet -from ..base import Set if TYPE_CHECKING: from .floatset import FloatSet @@ -130,7 +130,7 @@ def element_n(self, n: int) -> int: super().element_n(n) return intset_value_n(self._inner, n + 1) - def elements(self) -> List[int]: + def elements(self) -> list[int]: """ Returns the elements in ``self``. @@ -176,7 +176,7 @@ def scale(self, width: int) -> IntSet: """ return self.shift_scale(None, width) - def shift_scale(self, delta: Optional[int], width: Optional[int]) -> IntSet: + def shift_scale(self, delta: int | None, width: int | None) -> IntSet: """ Returns a new ``IntSet`` instance with all elements shifted by ``delta`` and scaled to so that the encompassing span has width @@ -192,15 +192,11 @@ def shift_scale(self, delta: Optional[int], width: Optional[int]) -> IntSet: MEOS Functions: intset_shift_scale """ - return IntSet( - _inner=intset_shift_scale( - self._inner, delta, width, delta is not None, width is not None - ) - ) + return IntSet(_inner=intset_shift_scale(self._inner, delta, width, delta is not None, width is not None)) # ------------------------- Topological Operations -------------------------------- - def contains(self, content: Union[IntSet, int]) -> bool: + def contains(self, content: IntSet | int) -> bool: """ Returns whether ``self`` contains ``content``. @@ -220,7 +216,7 @@ def contains(self, content: Union[IntSet, int]) -> bool: # ------------------------- Position Operations -------------------------------- - def is_left(self, content: Union[IntSet, int]) -> bool: + def is_left(self, content: IntSet | int) -> bool: """ Returns whether ``self`` is strictly to the left of ``other``. That is, ``self`` ends before ``other`` starts. @@ -239,7 +235,7 @@ def is_left(self, content: Union[IntSet, int]) -> bool: else: return super().is_left(content) - def is_over_or_left(self, content: Union[IntSet, int]) -> bool: + def is_over_or_left(self, content: IntSet | int) -> bool: """ Returns whether ``self`` is to the left of ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same value). @@ -258,7 +254,7 @@ def is_over_or_left(self, content: Union[IntSet, int]) -> bool: else: return super().is_over_or_left(content) - def is_right(self, content: Union[IntSet, int]) -> bool: + def is_right(self, content: IntSet | int) -> bool: """ Returns whether ``self`` is strictly to the right of ``other``. That is, ``self`` ends after ``other`` starts. @@ -277,7 +273,7 @@ def is_right(self, content: Union[IntSet, int]) -> bool: else: return super().is_right(content) - def is_over_or_right(self, content: Union[IntSet, int]) -> bool: + def is_over_or_right(self, content: IntSet | int) -> bool: """ Returns whether ``self`` is to the right of ``other`` allowing overlap. That is, ``self`` starts before ``other`` ends (or at the same value). @@ -299,10 +295,10 @@ def is_over_or_right(self, content: Union[IntSet, int]) -> bool: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: int) -> Optional[int]: ... + def intersection(self, other: int) -> int | None: ... @overload - def intersection(self, other: IntSet) -> Optional[IntSet]: ... + def intersection(self, other: IntSet) -> IntSet | None: ... def intersection(self, other): """ @@ -326,7 +322,7 @@ def intersection(self, other): else: return super().intersection(other) - def minus(self, other: Union[IntSet, int]) -> Optional[IntSet]: + def minus(self, other: IntSet | int) -> IntSet | None: """ Returns the difference of ``self`` and ``other``. @@ -348,7 +344,7 @@ def minus(self, other: Union[IntSet, int]) -> Optional[IntSet]: else: return super().minus(other) - def subtract_from(self, other: int) -> Optional[int]: + def subtract_from(self, other: int) -> int | None: """ Returns the difference of ``other`` and ``self``. @@ -366,7 +362,7 @@ def subtract_from(self, other: int) -> Optional[int]: """ return minus_int_set(other, self._inner) - def union(self, other: Union[IntSet, int]) -> IntSet: + def union(self, other: IntSet | int) -> IntSet: """ Returns the union of ``self`` and ``other``. @@ -390,7 +386,7 @@ def union(self, other: Union[IntSet, int]) -> IntSet: # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[int, IntSet, IntSpan, IntSpanSet]) -> int: + def distance(self, other: int | IntSet | IntSpan | IntSpanSet) -> int: """ Returns the distance between ``self`` and ``other``. @@ -411,9 +407,7 @@ def distance(self, other: Union[int, IntSet, IntSpan, IntSpanSet]) -> int: return distance_set_int(self._inner, other) elif isinstance(other, IntSet): return distance_intset_intset(self._inner, other._inner) - elif isinstance(other, IntSpan): - return self.to_spanset().distance(other) - elif isinstance(other, IntSpanSet): + elif isinstance(other, (IntSpan, IntSpanSet)): return self.to_spanset().distance(other) else: return super().distance(other) diff --git a/pymeos/collections/number/intspan.py b/pymeos/collections/number/intspan.py index e9b06e39..a42238d8 100644 --- a/pymeos/collections/number/intspan.py +++ b/pymeos/collections/number/intspan.py @@ -1,44 +1,44 @@ from __future__ import annotations -from typing import Union, overload, Optional, TYPE_CHECKING +from typing import TYPE_CHECKING, overload from pymeos_cffi import ( - intspan_in, - intspan_lower, - intspan_upper, - intspan_shift_scale, - contains_span_int, adjacent_span_int, - intspan_width, + contains_span_int, + distance_intspan_intspan, + distance_intspanset_intspan, + distance_span_int, int_to_span, - span_eq, - left_span_int, - overleft_span_int, - right_span_int, - overright_span_int, intersection_span_int, intersection_span_span, intersection_spanset_span, + intspan_in, + intspan_lower, + intspan_make, + intspan_out, + intspan_shift_scale, + intspan_to_floatspan, + intspan_upper, + intspan_width, + left_span_int, minus_span_int, minus_span_span, minus_spanset_span, + overleft_span_int, + overright_span_int, + right_span_int, + span_eq, union_span_int, union_span_span, union_spanset_span, - intspan_out, - intspan_make, - distance_span_int, - intspan_to_floatspan, - distance_intspan_intspan, - distance_intspanset_intspan, ) from ..base import Span if TYPE_CHECKING: + from .floatspan import FloatSpan from .intset import IntSet from .intspanset import IntSpanSet - from .floatspan import FloatSpan class IntSpan(Span[int]): @@ -181,7 +181,7 @@ def scale(self, width: int) -> IntSpan: """ return self.shift_scale(None, width) - def shift_scale(self, delta: Optional[int], width: Optional[int]) -> IntSpan: + def shift_scale(self, delta: int | None, width: int | None) -> IntSpan: """ Return a new ``IntSpan`` with the lower and upper bounds shifted by ``delta`` and scaled so that the width is ``width``. @@ -198,14 +198,12 @@ def shift_scale(self, delta: Optional[int], width: Optional[int]) -> IntSpan: """ d = delta if delta is not None else 0 w = width if width is not None else 0 - modified = intspan_shift_scale( - self._inner, d, w, delta is not None, width is not None - ) + modified = intspan_shift_scale(self._inner, d, w, delta is not None, width is not None) return IntSpan(_inner=modified) # ------------------------- Topological Operations -------------------------------- - def is_adjacent(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_adjacent(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -224,7 +222,7 @@ def is_adjacent(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_adjacent(other) - def contains(self, content: Union[int, IntSpan, IntSpanSet]) -> bool: + def contains(self, content: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` contains ``content``. @@ -242,7 +240,7 @@ def contains(self, content: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().contains(content) - def is_same(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_same(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` and the bounding tstzspan of ``other`` is the same. @@ -262,7 +260,7 @@ def is_same(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: return super().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_left(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is strictly left ``other``. That is, ``self`` ends before ``other`` starts. @@ -281,7 +279,7 @@ def is_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_left(other) - def is_over_or_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_over_or_left(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is left ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same value). @@ -300,7 +298,7 @@ def is_over_or_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_over_or_left(other) - def is_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_right(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is strictly right ``other``. That is, ``self`` starts after ``other`` ends. @@ -319,7 +317,7 @@ def is_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_right(other) - def is_over_or_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_over_or_right(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is right ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same value). @@ -339,7 +337,7 @@ def is_over_or_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: return super().is_over_or_right(other) # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[int, IntSet, IntSpan, IntSpanSet]) -> int: + def distance(self, other: int | IntSet | IntSpan | IntSpanSet) -> int: """ Returns the distance between ``self`` and ``other``. @@ -368,13 +366,13 @@ def distance(self, other: Union[int, IntSet, IntSpan, IntSpanSet]) -> int: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: int) -> Optional[int]: ... + def intersection(self, other: int) -> int | None: ... @overload - def intersection(self, other: IntSpan) -> Optional[IntSpan]: ... + def intersection(self, other: IntSpan) -> IntSpan | None: ... @overload - def intersection(self, other: IntSpanSet) -> Optional[IntSpanSet]: ... + def intersection(self, other: IntSpanSet) -> IntSpanSet | None: ... def intersection(self, other): """ @@ -404,7 +402,7 @@ def intersection(self, other): else: super().intersection(other) - def minus(self, other: Union[int, IntSpan, IntSpanSet]) -> IntSpanSet: + def minus(self, other: int | IntSpan | IntSpanSet) -> IntSpanSet: """ Returns the difference of ``self`` and ``other``. @@ -429,7 +427,7 @@ def minus(self, other: Union[int, IntSpan, IntSpanSet]) -> IntSpanSet: result = super().minus(other) return IntSpanSet(_inner=result) if result is not None else None - def union(self, other: Union[int, IntSpan, IntSpanSet]) -> IntSpanSet: + def union(self, other: int | IntSpan | IntSpanSet) -> IntSpanSet: """ Returns the union of ``self`` and ``other``. diff --git a/pymeos/collections/number/intspanset.py b/pymeos/collections/number/intspanset.py index ed559738..3ef36b70 100644 --- a/pymeos/collections/number/intspanset.py +++ b/pymeos/collections/number/intspanset.py @@ -1,35 +1,35 @@ from __future__ import annotations -from typing import Union, overload, Optional, TYPE_CHECKING, List +from typing import TYPE_CHECKING, overload from pymeos_cffi import ( - intspanset_in, - intspanset_out, - intspanset_width, - intspanset_shift_scale, adjacent_spanset_int, contains_spanset_int, - spanset_eq, + distance_intspanset_intspan, + distance_intspanset_intspanset, + distance_spanset_int, int_to_spanset, + intersection_spanset_int, + intspanset_in, + intspanset_out, + intspanset_shift_scale, + intspanset_to_floatspanset, + intspanset_width, left_spanset_int, + minus_spanset_int, overleft_spanset_int, - right_spanset_int, overright_spanset_int, - distance_spanset_int, - intersection_spanset_int, + right_spanset_int, + spanset_eq, union_spanset_int, - minus_spanset_int, - intspanset_to_floatspanset, - distance_intspanset_intspan, - distance_intspanset_intspanset, ) from ..base import SpanSet if TYPE_CHECKING: + from .floatspanset import FloatSpanSet from .intset import IntSet from .intspan import IntSpan - from .floatspanset import FloatSpanSet class IntSpanSet(SpanSet[int]): @@ -55,9 +55,7 @@ class IntSpanSet(SpanSet[int]): _mobilitydb_name = "intspanset" _parse_function = intspanset_in - _parse_value_function = lambda span: ( - intspanset_in(span)[0] if isinstance(span, str) else span._inner[0] - ) + _parse_value_function = lambda span: (intspanset_in(span)[0] if isinstance(span, str) else span._inner[0]) # ------------------------- Output ---------------------------------------- def __str__(self): @@ -104,7 +102,7 @@ def to_floatspanset(self) -> FloatSpanSet: # ------------------------- Accessors ------------------------------------- - def width(self, ignore_gaps: Optional[bool] = False) -> float: + def width(self, ignore_gaps: bool | None = False) -> float: """ Returns the width of the spanset. By default, i.e., when the second argument is False, the function takes into account the gaps within, @@ -164,7 +162,7 @@ def span_n(self, n: int) -> IntSpan: return IntSpan(_inner=super().span_n(n)) - def spans(self) -> List[IntSpan]: + def spans(self) -> list[IntSpan]: """ Returns the list of spans in ``self``. Returns: @@ -212,7 +210,7 @@ def scale(self, width: int) -> IntSpanSet: """ return self.shift_scale(None, width) - def shift_scale(self, delta: Optional[int], width: Optional[int]) -> IntSpanSet: + def shift_scale(self, delta: int | None, width: int | None) -> IntSpanSet: """ Return a new ``IntSpanSet`` with the lower and upper bounds shifted by ``delta`` and scaled so that the width is ``width``. @@ -229,14 +227,12 @@ def shift_scale(self, delta: Optional[int], width: Optional[int]) -> IntSpanSet: """ d = delta if delta is not None else 0 w = width if width is not None else 0 - modified = intspanset_shift_scale( - self._inner, d, w, delta is not None, width is not None - ) + modified = intspanset_shift_scale(self._inner, d, w, delta is not None, width is not None) return IntSpanSet(_inner=modified) # ------------------------- Topological Operations -------------------------------- - def is_adjacent(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_adjacent(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -256,7 +252,7 @@ def is_adjacent(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_adjacent(other) - def contains(self, content: Union[int, IntSpan, IntSpanSet]) -> bool: + def contains(self, content: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` contains ``content``. @@ -275,7 +271,7 @@ def contains(self, content: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().contains(content) - def is_same(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_same(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` and the bounding tstzspan of ``other`` is the same. @@ -295,7 +291,7 @@ def is_same(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: return super().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_left(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is strictly left of ``other``. That is, ``self`` ends before ``other`` starts. @@ -314,7 +310,7 @@ def is_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_left(other) - def is_over_or_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_over_or_left(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is left ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same value). @@ -333,7 +329,7 @@ def is_over_or_left(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_over_or_left(other) - def is_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_right(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is strictly right ``other``. That is, ``self`` starts after ``other`` ends. @@ -352,7 +348,7 @@ def is_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: else: return super().is_right(other) - def is_over_or_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: + def is_over_or_right(self, other: int | IntSpan | IntSpanSet) -> bool: """ Returns whether ``self`` is right ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same value). @@ -373,7 +369,7 @@ def is_over_or_right(self, other: Union[int, IntSpan, IntSpanSet]) -> bool: return super().is_over_or_right(other) # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[int, IntSet, IntSpan, IntSpanSet]) -> int: + def distance(self, other: int | IntSet | IntSpan | IntSpanSet) -> int: """ Returns the distance between ``self`` and ``other``. @@ -403,13 +399,13 @@ def distance(self, other: Union[int, IntSet, IntSpan, IntSpanSet]) -> int: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: int) -> Optional[int]: ... + def intersection(self, other: int) -> int | None: ... @overload - def intersection(self, other: IntSpan) -> Optional[IntSpanSet]: ... + def intersection(self, other: IntSpan) -> IntSpanSet | None: ... @overload - def intersection(self, other: IntSpanSet) -> Optional[IntSpanSet]: ... + def intersection(self, other: IntSpanSet) -> IntSpanSet | None: ... def intersection(self, other): """ @@ -448,7 +444,7 @@ def __mul__(self, other): """ return self.intersection(other) - def minus(self, other: Union[int, IntSpan, IntSpanSet]) -> IntSpanSet: + def minus(self, other: int | IntSpan | IntSpanSet) -> IntSpanSet: """ Returns the difference of ``self`` and ``other``. @@ -483,7 +479,7 @@ def __sub__(self, other): """ return self.minus(other) - def union(self, other: Union[int, IntSpan, IntSpanSet]) -> IntSpanSet: + def union(self, other: int | IntSpan | IntSpanSet) -> IntSpanSet: """ Returns the union of ``self`` and ``other``. diff --git a/pymeos/collections/text/textset.py b/pymeos/collections/text/textset.py index f58e1af9..0a1caddf 100644 --- a/pymeos/collections/text/textset.py +++ b/pymeos/collections/text/textset.py @@ -1,6 +1,6 @@ from __future__ import annotations -from typing import Optional, overload, Union +from typing import overload from pymeos_cffi import * @@ -112,7 +112,7 @@ def elements(self): # ------------------------- Topological Operations -------------------------------- - def contains(self, content: Union[TextSet, str]) -> bool: + def contains(self, content: TextSet | str) -> bool: """ Returns whether ``self`` contains ``content``. @@ -158,10 +158,10 @@ def uppercase(self): # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: str) -> Optional[str]: ... + def intersection(self, other: str) -> str | None: ... @overload - def intersection(self, other: TextSet) -> Optional[TextSet]: ... + def intersection(self, other: TextSet) -> TextSet | None: ... def intersection(self, other): """ @@ -185,7 +185,7 @@ def intersection(self, other): else: return super().intersection(other) - def minus(self, other: Union[TextSet, str]) -> Optional[TextSet]: + def minus(self, other: TextSet | str) -> TextSet | None: """ Returns the difference of ``self`` and ``other``. @@ -207,7 +207,7 @@ def minus(self, other: Union[TextSet, str]) -> Optional[TextSet]: else: return super().minus(other) - def subtract_from(self, other: str) -> Optional[str]: + def subtract_from(self, other: str) -> str | None: """ Returns the difference of ``other`` and ``self``. @@ -226,7 +226,7 @@ def subtract_from(self, other: str) -> Optional[str]: result = minus_text_set(other, self._inner) return text2cstring(result[0]) if result is not None else None - def union(self, other: Union[TextSet, str]) -> TextSet: + def union(self, other: TextSet | str) -> TextSet: """ Returns the union of ``self`` and ``other``. diff --git a/pymeos/collections/time/__init__.py b/pymeos/collections/time/__init__.py index 88b53ae9..8cda4c8f 100644 --- a/pymeos/collections/time/__init__.py +++ b/pymeos/collections/time/__init__.py @@ -1,11 +1,12 @@ -from .tstzset import TsTzSet +from datetime import date, datetime, timedelta + from .dateset import DateSet -from .tstzspan import TsTzSpan from .datespan import DateSpan -from .tstzspanset import TsTzSpanSet from .datespanset import DateSpanSet from .time import Time, TimeDate -from datetime import datetime, timedelta, date +from .tstzset import TsTzSet +from .tstzspan import TsTzSpan +from .tstzspanset import TsTzSpanSet __all__ = [ "TimeDate", diff --git a/pymeos/collections/time/dateset.py b/pymeos/collections/time/dateset.py index 55def40a..61d38dba 100644 --- a/pymeos/collections/time/dateset.py +++ b/pymeos/collections/time/dateset.py @@ -1,46 +1,42 @@ from __future__ import annotations -from datetime import date, timedelta, datetime -from typing import TYPE_CHECKING, List, Optional, Union, overload +from datetime import date, datetime, timedelta +from typing import TYPE_CHECKING, overload -from dateutil.parser import parse from pymeos_cffi import ( - dateset_in, - pg_date_in, + after_set_date, + before_set_date, + contains_set_date, + date_adt_to_date, date_to_date_adt, + dateset_end_value, + dateset_in, dateset_make, dateset_out, + dateset_shift_scale, dateset_start_value, - date_adt_to_date, - dateset_end_value, dateset_value_n, dateset_values, - dateset_shift_scale, - contains_set_date, - before_set_date, - overbefore_set_date, - overafter_set_date, - after_set_date, + distance_dateset_dateset, distance_set_date, intersection_set_date, intersection_set_set, + minus_date_set, minus_set_date, minus_set_set, - minus_date_set, + overafter_set_date, + overbefore_set_date, + pg_date_in, union_set_date, union_set_set, - distance_dateset_dateset, ) -from .timecollection import TimeCollection from ..base import Set +from .timecollection import TimeCollection if TYPE_CHECKING: from .datespan import DateSpan from .datespanset import DateSpanSet - from .tstzspanset import TsTzSpanSet - from .tstzspan import TsTzSpan - from .tstzspanset import TsTzSpanSet from .time import TimeDate @@ -67,9 +63,7 @@ class DateSet(Set[date], TimeCollection[date]): _mobilitydb_name = "dateset" _parse_function = dateset_in - _parse_value_function = lambda x: ( - pg_date_in(x) if isinstance(x, str) else date_to_date_adt(x) - ) + _parse_value_function = lambda x: (pg_date_in(x) if isinstance(x, str) else date_to_date_adt(x)) _make_function = dateset_make # ------------------------- Constructors ---------------------------------- @@ -159,7 +153,7 @@ def element_n(self, n: int) -> date: super().element_n(n) return date_adt_to_date(dateset_value_n(self._inner, n + 1)[0]) - def elements(self) -> List[date]: + def elements(self) -> list[date]: """ Returns the list of distinct dates in ``self``. Returns: @@ -172,7 +166,7 @@ def elements(self) -> List[date]: return [date_adt_to_date(tss[i]) for i in range(self.num_elements())] # ------------------------- Transformations ------------------------------- - def shift(self, delta: Union[timedelta, int]) -> DateSet: + def shift(self, delta: timedelta | int) -> DateSet: """ Returns a new :class:`DateSpanSet` that is the result of shifting ``self`` by ``delta`` @@ -192,7 +186,7 @@ def shift(self, delta: Union[timedelta, int]) -> DateSet: """ return self.shift_scale(shift=delta) - def scale(self, duration: Union[timedelta, int]) -> DateSet: + def scale(self, duration: timedelta | int) -> DateSet: """ Returns a new :class:`DateSet` that with the scaled so that the span of ``self`` is ``duration``. @@ -215,8 +209,8 @@ def scale(self, duration: Union[timedelta, int]) -> DateSet: def shift_scale( self, - shift: Union[int, timedelta, None] = None, - duration: Union[int, timedelta, None] = None, + shift: int | timedelta | None = None, + duration: int | timedelta | None = None, ) -> DateSet: """ Returns a new :class:`DateSet` that is the result of shifting and scaling @@ -237,27 +231,15 @@ def shift_scale( MEOS Functions: dateset_shift_scale """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" - shift = ( - shift.days - if isinstance(shift, timedelta) - else int(shift) if shift is not None else 0 - ) - duration = ( - duration.days - if isinstance(duration, timedelta) - else int(duration) if duration is not None else 0 - ) - tss = dateset_shift_scale( - self._inner, shift, duration, shift != 0, duration != 0 - ) + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" + shift = shift.days if isinstance(shift, timedelta) else int(shift) if shift is not None else 0 + duration = duration.days if isinstance(duration, timedelta) else int(duration) if duration is not None else 0 + tss = dateset_shift_scale(self._inner, shift, duration, shift != 0, duration != 0) return DateSet(_inner=tss) # ------------------------- Topological Operations ------------------------ - def contains(self, content: Union[date, datetime, DateSet]) -> bool: + def contains(self, content: date | datetime | DateSet) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -309,7 +291,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps(self, other: Union[date, DateSet, DateSpan, DateSpanSet]) -> bool: + def overlaps(self, other: date | DateSet | DateSpan | DateSpanSet) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -371,9 +353,7 @@ def is_left(self, other: TimeDate) -> bool: if isinstance(other, date): return before_set_date(self._inner, date_to_date_adt(other)) - elif isinstance(other, DateSpan): - return self.to_span().is_left(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_span().is_left(other) else: return super().is_left(other) @@ -405,9 +385,7 @@ def is_over_or_left(self, other: TimeDate) -> bool: if isinstance(other, date): return overbefore_set_date(self._inner, date_to_date_adt(other)) - elif isinstance(other, DateSpan): - return self.to_span().is_over_or_left(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_span().is_over_or_left(other) else: return super().is_over_or_left(other) @@ -439,9 +417,7 @@ def is_over_or_right(self, other: TimeDate) -> bool: if isinstance(other, date): return overafter_set_date(self._inner, date_to_date_adt(other)) - elif isinstance(other, DateSpan): - return self.to_span().is_over_or_after(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_span().is_over_or_after(other) else: return super().is_over_or_left(other) @@ -473,9 +449,7 @@ def is_right(self, other: TimeDate) -> bool: if isinstance(other, date): return after_set_date(self._inner, date_to_date_adt(other)) - elif isinstance(other, DateSpan): - return self.to_span().is_after(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_span().is_after(other) else: return super().is_over_or_left(other) @@ -499,14 +473,10 @@ def distance(self, other: TimeDate) -> timedelta: from .datespanset import DateSpanSet if isinstance(other, date): - return timedelta( - days=distance_set_date(self._inner, date_to_date_adt(other)) - ) + return timedelta(days=distance_set_date(self._inner, date_to_date_adt(other))) elif isinstance(other, DateSet): return timedelta(days=distance_dateset_dateset(self._inner, other._inner)) - elif isinstance(other, DateSpan): - return self.to_spanset().distance(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_spanset().distance(other) else: return super().distance(other) @@ -514,14 +484,12 @@ def distance(self, other: TimeDate) -> timedelta: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: Union[date, DateSet]) -> Optional[DateSet]: ... + def intersection(self, other: date | DateSet) -> DateSet | None: ... @overload - def intersection( - self, other: Union[DateSpan, DateSpanSet] - ) -> Optional[DateSpanSet]: ... + def intersection(self, other: DateSpan | DateSpanSet) -> DateSpanSet | None: ... - def intersection(self, other: TimeDate) -> Optional[TimeDate]: + def intersection(self, other: TimeDate) -> TimeDate | None: """ Returns the temporal intersection of ``self`` and ``other``. @@ -544,20 +512,18 @@ def intersection(self, other: TimeDate) -> Optional[TimeDate]: elif isinstance(other, DateSet): result = intersection_set_set(self._inner, other._inner) return DateSet(_inner=result) if result is not None else None - elif isinstance(other, DateSpan): - return self.to_spanset().intersection(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_spanset().intersection(other) else: return super().intersection(other) @overload - def minus(self, other: Union[date, DateSet]) -> Optional[DateSet]: ... + def minus(self, other: date | DateSet) -> DateSet | None: ... @overload - def minus(self, other: Union[DateSpan, DateSpanSet]) -> Optional[DateSpanSet]: ... + def minus(self, other: DateSpan | DateSpanSet) -> DateSpanSet | None: ... - def minus(self, other: TimeDate) -> Optional[TimeDate]: + def minus(self, other: TimeDate) -> TimeDate | None: """ Returns the temporal difference of ``self`` and ``other``. @@ -580,14 +546,12 @@ def minus(self, other: TimeDate) -> Optional[TimeDate]: elif isinstance(other, DateSet): result = minus_set_set(self._inner, other._inner) return DateSet(_inner=result) if result is not None else None - elif isinstance(other, DateSpan): - return self.to_spanset().minus(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_spanset().minus(other) else: return super().minus(other) - def subtract_from(self, other: date) -> Optional[date]: + def subtract_from(self, other: date) -> date | None: """ Returns the difference of ``other`` and ``self``. @@ -606,12 +570,12 @@ def subtract_from(self, other: date) -> Optional[date]: return date_adt_to_date(minus_date_set(date_to_date_adt(other), self._inner)) @overload - def union(self, other: Union[date, DateSet]) -> DateSet: ... + def union(self, other: date | DateSet) -> DateSet: ... @overload - def union(self, other: Union[DateSpan, DateSpanSet]) -> DateSpanSet: ... + def union(self, other: DateSpan | DateSpanSet) -> DateSpanSet: ... - def union(self, other: TimeDate) -> Union[DateSpanSet, DateSet]: + def union(self, other: TimeDate) -> DateSpanSet | DateSet: """ Returns the temporal union of ``self`` and ``other``. @@ -632,9 +596,7 @@ def union(self, other: TimeDate) -> Union[DateSpanSet, DateSet]: return DateSet(_inner=union_set_date(self._inner, date_to_date_adt(other))) elif isinstance(other, DateSet): return DateSet(_inner=union_set_set(self._inner, other._inner)) - elif isinstance(other, DateSpan): - return self.to_spanset().union(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): return self.to_spanset().union(other) else: return super().union(other) @@ -645,6 +607,4 @@ def union(self, other: TimeDate) -> Union[DateSpanSet, DateSet]: def plot(self, *args, **kwargs): from ...plotters import TimePlotter - return TimePlotter.plot_tstzspanset( - self.to_spanset().to_tstzspanset(), *args, **kwargs - ) + return TimePlotter.plot_tstzspanset(self.to_spanset().to_tstzspanset(), *args, **kwargs) diff --git a/pymeos/collections/time/datespan.py b/pymeos/collections/time/datespan.py index 1639b6f9..c2a70642 100644 --- a/pymeos/collections/time/datespan.py +++ b/pymeos/collections/time/datespan.py @@ -1,47 +1,46 @@ from __future__ import annotations from datetime import date, timedelta -from typing import TYPE_CHECKING, Union, Optional, overload +from typing import TYPE_CHECKING, overload from _meos_cffi.lib import distance_datespanset_datespan -from dateutil.parser import parse from pymeos_cffi import ( adjacent_span_date, - datespan_in, + after_span_date, + before_span_date, + contains_span_date, + date_adt_to_date, date_to_date_adt, - pg_date_in, + datespan_duration, + datespan_in, + datespan_lower, datespan_make, datespan_out, + datespan_shift_scale, datespan_to_tstzspan, - date_adt_to_date, - interval_to_timedelta, - datespan_duration, datespan_upper, - datespan_lower, - datespan_shift_scale, - union_span_date, - minus_span_date, - minus_span_span, - minus_span_spanset, + distance_span_date, intersection_span_date, intersection_span_span, intersection_spanset_span, - distance_span_date, + interval_to_timedelta, + minus_span_date, + minus_span_span, + minus_span_spanset, overafter_span_date, - after_span_date, overbefore_span_date, - before_span_date, - contains_span_date, + pg_date_in, + union_span_date, ) -from .timecollection import TimeCollection from ..base import Span +from .timecollection import TimeCollection if TYPE_CHECKING: from .dateset import DateSet from .datespanset import DateSpanSet - from .tstzspan import TsTzSpan from .time import TimeDate + from .tstzspan import TsTzSpan class DateSpan(Span[date], TimeCollection[date]): @@ -69,9 +68,7 @@ class DateSpan(Span[date], TimeCollection[date]): _mobilitydb_name = "datespan" _parse_function = datespan_in - _parse_value_function = lambda x: ( - pg_date_in(x) if isinstance(x, str) else date_to_date_adt(x) - ) + _parse_value_function = lambda x: (pg_date_in(x) if isinstance(x, str) else date_to_date_adt(x)) _make_function = datespan_make # ------------------------- Constructors ---------------------------------- @@ -172,7 +169,7 @@ def duration_in_days(self) -> float: return self.width() # ------------------------- Transformations ------------------------------- - def shift(self, delta: Union[timedelta, int]) -> DateSpan: + def shift(self, delta: timedelta | int) -> DateSpan: """ Returns a new :class:`DateSpan` that is the result of shifting ``self`` by ``delta``. @@ -192,7 +189,7 @@ def shift(self, delta: Union[timedelta, int]) -> DateSpan: """ return self.shift_scale(shift=delta) - def scale(self, duration: Union[timedelta, int]) -> DateSpan: + def scale(self, duration: timedelta | int) -> DateSpan: """ Returns a new :class:`DateSpan` that starts as ``self`` but has duration ``duration``. @@ -215,8 +212,8 @@ def scale(self, duration: Union[timedelta, int]) -> DateSpan: def shift_scale( self, - shift: Union[int, timedelta, None] = None, - duration: Union[int, timedelta, None] = None, + shift: int | timedelta | None = None, + duration: int | timedelta | None = None, ) -> DateSpan: """ Returns a new :class:`DateSpan` that starts at ``self`` shifted by ``shift`` and @@ -237,29 +234,17 @@ def shift_scale( MEOS Functions: datespan_shift_scale """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" - - shift = ( - shift.days - if isinstance(shift, timedelta) - else int(shift) if shift is not None else 0 - ) - duration = ( - duration.days - if isinstance(duration, timedelta) - else int(duration) if duration is not None else 0 - ) - - modified = datespan_shift_scale( - self._inner, shift, duration, shift != 0, duration != 0 - ) + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" + + shift = shift.days if isinstance(shift, timedelta) else int(shift) if shift is not None else 0 + duration = duration.days if isinstance(duration, timedelta) else int(duration) if duration is not None else 0 + + modified = datespan_shift_scale(self._inner, shift, duration, shift != 0, duration != 0) return DateSpan(_inner=modified) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[date, DateSpan, DateSpanSet]) -> bool: + def is_adjacent(self, other: date | DateSpan | DateSpanSet) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -464,35 +449,25 @@ def distance(self, other: TimeDate) -> timedelta: from .datespanset import DateSpanSet if isinstance(other, date): - return timedelta( - days=distance_span_date(self._inner, date_to_date_adt(other)) - ) + return timedelta(days=distance_span_date(self._inner, date_to_date_adt(other))) elif isinstance(other, DateSet): return self.distance(other.to_spanset()) - elif isinstance(other, DateSpan): - return timedelta( - days=distance_datespanset_datespan(self._inner, other._inner) - ) - elif isinstance(other, DateSpanSet): - return timedelta( - days=distance_datespanset_datespan(self._inner, other._inner) - ) + elif isinstance(other, (DateSpan, DateSpanSet)): + return timedelta(days=distance_datespanset_datespan(self._inner, other._inner)) else: return super().distance(other) # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: date) -> Optional[date]: ... + def intersection(self, other: date) -> date | None: ... @overload - def intersection(self, other: DateSpan) -> Optional[DateSpan]: ... + def intersection(self, other: DateSpan) -> DateSpan | None: ... @overload - def intersection( - self, other: Union[DateSet, DateSpanSet] - ) -> Optional[DateSpanSet]: ... + def intersection(self, other: DateSet | DateSpanSet) -> DateSpanSet | None: ... - def intersection(self, other: TimeDate) -> Optional[TimeDate]: + def intersection(self, other: TimeDate) -> TimeDate | None: """ Returns the temporal intersection of ``self`` and ``other``. @@ -506,8 +481,8 @@ def intersection(self, other: TimeDate) -> Optional[TimeDate]: intersection_span_span, intersection_spanset_span, intersection_span_date """ - from .datespanset import DateSpanSet from .dateset import DateSet + from .datespanset import DateSpanSet if isinstance(other, date): result = intersection_span_date(self._inner, date_to_date_adt(other)) @@ -536,8 +511,8 @@ def minus(self, other: TimeDate) -> DateSpanSet: MEOS Functions: minus_span_date, minus_span_spanset, minus_span_span """ - from .datespanset import DateSpanSet from .dateset import DateSet + from .datespanset import DateSpanSet if isinstance(other, date): result = minus_span_date(self._inner, date_to_date_adt(other)) @@ -564,16 +539,14 @@ def union(self, other: TimeDate) -> DateSpanSet: MEOS Functions: union_span_date, union_spanset_span, union_span_span """ - from .datespanset import DateSpanSet from .dateset import DateSet + from .datespanset import DateSpanSet if isinstance(other, date): result = union_span_date(self._inner, date_to_date_adt(other)) elif isinstance(other, DateSet): result = super().union(other.to_spanset()) - elif isinstance(other, DateSpan): - result = super().union(other) - elif isinstance(other, DateSpanSet): + elif isinstance(other, (DateSpan, DateSpanSet)): result = super().union(other) else: raise TypeError(f"Operation not supported with type {other.__class__}") diff --git a/pymeos/collections/time/datespanset.py b/pymeos/collections/time/datespanset.py index 8171f587..2b177f21 100644 --- a/pymeos/collections/time/datespanset.py +++ b/pymeos/collections/time/datespanset.py @@ -1,47 +1,45 @@ from __future__ import annotations -from datetime import timedelta, date -from typing import Optional, Union, List, overload -from typing import TYPE_CHECKING +from datetime import date, timedelta +from typing import TYPE_CHECKING, overload from _meos_cffi.lib import ( distance_datespanset_datespan, distance_datespanset_datespanset, ) from pymeos_cffi import ( - datespanset_in, - datespan_in, - datespanset_out, - datespanset_to_tstzspanset, - interval_to_timedelta, - datespanset_duration, - datespanset_num_dates, + after_spanset_date, + before_spanset_date, + contains_spanset_date, date_adt_to_date, - datespanset_start_date, - datespanset_end_date, + date_to_date_adt, + datespan_in, datespanset_date_n, datespanset_dates, + datespanset_duration, + datespanset_end_date, + datespanset_in, + datespanset_num_dates, + datespanset_out, datespanset_shift_scale, - date_to_date_adt, - contains_spanset_date, - before_spanset_date, - overbefore_spanset_date, - overafter_spanset_date, - after_spanset_date, + datespanset_start_date, + datespanset_to_tstzspanset, distance_spanset_date, intersection_spanset_date, + interval_to_timedelta, minus_spanset_date, + overafter_spanset_date, + overbefore_spanset_date, union_spanset_date, ) -from .timecollection import TimeCollection from ..base.spanset import SpanSet +from .timecollection import TimeCollection if TYPE_CHECKING: - from .tstzspan import TsTzSpan - from .tstzspanset import TsTzSpanSet from .datespan import DateSpan from .time import TimeDate + from .tstzspanset import TsTzSpanSet class DateSpanSet(SpanSet[date], TimeCollection[date]): @@ -115,7 +113,7 @@ def to_tstzspanset(self) -> TsTzSpanSet: return TsTzSpanSet(_inner=datespanset_to_tstzspanset(self._inner)) # ------------------------- Accessors ------------------------------------- - def duration(self, ignore_gaps: Optional[bool] = False) -> timedelta: + def duration(self, ignore_gaps: bool | None = False) -> timedelta: """ Returns the duration of ``self``. By default, i.e., when ``ignore_gaps`` is ``False``, the function takes into account the gaps between the @@ -183,7 +181,7 @@ def date_n(self, n: int) -> date: raise IndexError(f"Index {n} out of bounds") return date_adt_to_date(datespanset_date_n(self._inner, n + 1)) - def dates(self) -> List[date]: + def dates(self) -> list[date]: """ Returns the list of distinct dates in ``self``. Returns: @@ -234,7 +232,7 @@ def span_n(self, n: int) -> DateSpan: return DateSpan(_inner=super().span_n(n)) - def spans(self) -> List[DateSpan]: + def spans(self) -> list[DateSpan]: """ Returns the list of :class:`DateSpan` in ``self``. Returns: @@ -249,7 +247,7 @@ def spans(self) -> List[DateSpan]: return [DateSpan(_inner=ps[i]) for i in range(self.num_spans())] # ------------------------- Transformations ------------------------------- - def shift(self, delta: Union[timedelta, int]) -> DateSpanSet: + def shift(self, delta: timedelta | int) -> DateSpanSet: """ Returns a new :class:`DateSpanSet` that is the result of shifting ``self`` by ``delta`` @@ -269,7 +267,7 @@ def shift(self, delta: Union[timedelta, int]) -> DateSpanSet: """ return self.shift_scale(shift=delta) - def scale(self, duration: Union[timedelta, int]) -> DateSpanSet: + def scale(self, duration: timedelta | int) -> DateSpanSet: """ Returns a new :class:`DateSpanSet` that starts as ``self`` but has duration ``duration`` @@ -292,8 +290,8 @@ def scale(self, duration: Union[timedelta, int]) -> DateSpanSet: def shift_scale( self, - shift: Union[timedelta, int, None] = None, - duration: Union[timedelta, int, None] = None, + shift: timedelta | int | None = None, + duration: timedelta | int | None = None, ) -> DateSpanSet: """ Returns a new :class:`DateSpanSet` that starts at ``self`` shifted by ``shift`` @@ -314,29 +312,17 @@ def shift_scale( MEOS Functions: datespanset_shift_scale """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" - - shift = ( - shift.days - if isinstance(shift, timedelta) - else int(shift) if shift is not None else 0 - ) - duration = ( - duration.days - if isinstance(duration, timedelta) - else int(duration) if duration is not None else 0 - ) - - modified = datespanset_shift_scale( - self._inner, shift, duration, shift != 0, duration != 0 - ) + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" + + shift = shift.days if isinstance(shift, timedelta) else int(shift) if shift is not None else 0 + duration = duration.days if isinstance(duration, timedelta) else int(duration) if duration is not None else 0 + + modified = datespanset_shift_scale(self._inner, shift, duration, shift != 0, duration != 0) return DateSpanSet(_inner=modified) # ------------------------- Topological Operations ------------------------ - def contains(self, content: Union[TimeDate]) -> bool: + def contains(self, content: TimeDate) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -364,7 +350,7 @@ def contains(self, content: Union[TimeDate]) -> bool: else: return super().contains(content) - def overlaps(self, other: Union[TimeDate]) -> bool: + def overlaps(self, other: TimeDate) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -392,7 +378,7 @@ def overlaps(self, other: Union[TimeDate]) -> bool: return super().overlaps(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[TimeDate]) -> bool: + def is_left(self, other: TimeDate) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -419,7 +405,7 @@ def is_left(self, other: Union[TimeDate]) -> bool: else: return super().is_left(other) - def is_over_or_left(self, other: Union[TimeDate]) -> bool: + def is_over_or_left(self, other: TimeDate) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -447,7 +433,7 @@ def is_over_or_left(self, other: Union[TimeDate]) -> bool: else: return super().is_over_or_left(other) - def is_over_or_right(self, other: Union[TimeDate]) -> bool: + def is_over_or_right(self, other: TimeDate) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same time). @@ -475,7 +461,7 @@ def is_over_or_right(self, other: Union[TimeDate]) -> bool: else: return super().is_over_or_right(other) - def is_right(self, other: Union[TimeDate]) -> bool: + def is_right(self, other: TimeDate) -> bool: """ Returns whether ``self`` is strictly after ``other``.That is, ``self`` starts after ``other`` ends. @@ -522,19 +508,13 @@ def distance(self, other: TimeDate) -> timedelta: from .datespan import DateSpan if isinstance(other, date): - return timedelta( - days=distance_spanset_date(self._inner, date_to_date_adt(other)) - ) + return timedelta(days=distance_spanset_date(self._inner, date_to_date_adt(other))) elif isinstance(other, DateSet): return self.distance(other.to_spanset()) elif isinstance(other, DateSpan): - return timedelta( - days=distance_datespanset_datespan(self._inner, other._inner) - ) + return timedelta(days=distance_datespanset_datespan(self._inner, other._inner)) elif isinstance(other, DateSpanSet): - return timedelta( - days=distance_datespanset_datespanset(self._inner, other._inner) - ) + return timedelta(days=distance_datespanset_datespanset(self._inner, other._inner)) else: return super().distance(other) @@ -544,9 +524,9 @@ def distance(self, other: TimeDate) -> timedelta: def intersection(self, other: date) -> date: ... @overload - def intersection(self, other: Union[DateSpan, DateSpanSet]) -> DateSpanSet: ... + def intersection(self, other: DateSpan | DateSpanSet) -> DateSpanSet: ... - def intersection(self, other: TimeDate) -> Union[date, DateSpanSet]: + def intersection(self, other: TimeDate) -> date | DateSpanSet: """ Returns the temporal intersection of ``self`` and ``other``. diff --git a/pymeos/collections/time/time.py b/pymeos/collections/time/time.py index 61ace724..1ba6364c 100644 --- a/pymeos/collections/time/time.py +++ b/pymeos/collections/time/time.py @@ -1,40 +1,29 @@ -from datetime import datetime, date -from typing import Union - -from .tstzspan import TsTzSpan -from .tstzspanset import TsTzSpanSet -from .tstzset import TsTzSet +from datetime import date, datetime +from .dateset import DateSet from .datespan import DateSpan from .datespanset import DateSpanSet -from .dateset import DateSet +from .tstzset import TsTzSet +from .tstzspan import TsTzSpan +from .tstzspanset import TsTzSpanSet -Time = Union[ - datetime, - TsTzSet, - TsTzSpan, - TsTzSpanSet, -] +Time = datetime | TsTzSet | TsTzSpan | TsTzSpanSet """ -Union type that includes all Time types related to timestamps in PyMEOS: +Union type that includes all Time types related to timestamps in PyMEOS: -- :class:`~datetime.datetime` for timestamps -- :class:`~pymeos.time.tstzset.TsTzSet` for sets of timestamps -- :class:`~pymeos.time.tstzspan.TsTzSpan` for spans of time -- :class:`~pymeos.time.tstzspanset.TsTzSpanSet` for sets of spans of time +- :class:`~datetime.datetime` for timestamps +- :class:`~pymeos.time.tstzset.TsTzSet` for sets of timestamps +- :class:`~pymeos.time.tstzspan.TsTzSpan` for spans of time +- :class:`~pymeos.time.tstzspanset.TsTzSpanSet` for sets of spans of time """ -TimeDate = Union[ - date, - DateSet, - DateSpan, - DateSpanSet, -] +TimeDate = date | DateSet | DateSpan | DateSpanSet + """ -Union type that includes all Time types related to dates in PyMEOS: +Union type that includes all Time types related to dates in PyMEOS: -- :class:`~datetime.date` for dates -- :class:`~pymeos.time.dateset.DateSet` for sets of dates -- :class:`~pymeos.time.datespan.DateSpan` for spans of dates -- :class:`~pymeos.time.datespanset.DateSpanSet` for sets of spans of dates +- :class:`~datetime.date` for dates +- :class:`~pymeos.time.dateset.DateSet` for sets of dates +- :class:`~pymeos.time.datespan.DateSpan` for spans of dates +- :class:`~pymeos.time.datespanset.DateSpanSet` for sets of spans of dates """ diff --git a/pymeos/collections/time/tstzset.py b/pymeos/collections/time/tstzset.py index 6c91af52..3175880f 100644 --- a/pymeos/collections/time/tstzset.py +++ b/pymeos/collections/time/tstzset.py @@ -1,20 +1,19 @@ from __future__ import annotations from datetime import datetime, timedelta -from typing import Optional, List, Union, TYPE_CHECKING, overload, get_args +from typing import TYPE_CHECKING, get_args, overload -from dateutil.parser import parse from pymeos_cffi import * -from .timecollection import TimeCollection from ..base import Set +from .timecollection import TimeCollection if TYPE_CHECKING: + from ...boxes import Box from ...temporal import Temporal + from .time import Time from .tstzspan import TsTzSpan from .tstzspanset import TsTzSpanSet - from .time import Time - from ...boxes import Box class TsTzSet(Set[datetime], TimeCollection[datetime]): @@ -40,9 +39,7 @@ class TsTzSet(Set[datetime], TimeCollection[datetime]): _mobilitydb_name = "tstzset" _parse_function = tstzset_in - _parse_value_function = lambda x: ( - pg_timestamptz_in(x, -1) if isinstance(x, str) else datetime_to_timestamptz(x) - ) + _parse_value_function = lambda x: (pg_timestamptz_in(x, -1) if isinstance(x, str) else datetime_to_timestamptz(x)) _make_function = tstzset_make # ------------------------- Constructors ---------------------------------- @@ -110,7 +107,7 @@ def element_n(self, n: int) -> datetime: super().element_n(n) return timestamptz_to_datetime(tstzset_value_n(self._inner, n + 1)) - def elements(self) -> List[datetime]: + def elements(self) -> list[datetime]: """ Returns the list of distinct timestamps in ``self``. Returns: @@ -164,9 +161,7 @@ def scale(self, duration: timedelta) -> TsTzSet: """ return self.shift_scale(duration=duration) - def shift_scale( - self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None - ) -> TsTzSet: + def shift_scale(self, shift: timedelta | None = None, duration: timedelta | None = None) -> TsTzSet: """ Returns a new TsTzSet that is the result of shifting and scaling ``self``. @@ -186,9 +181,7 @@ def shift_scale( MEOS Functions: tstzset_shift_scale """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" tss = tstzset_shift_scale( self._inner, timedelta_to_interval(shift) if shift else None, @@ -197,7 +190,7 @@ def shift_scale( return TsTzSet(_inner=tss) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[TsTzSpan, TsTzSpanSet, Temporal, Box]) -> bool: + def is_adjacent(self, other: TsTzSpan | TsTzSpanSet | Temporal | Box) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -219,8 +212,8 @@ def is_adjacent(self, other: Union[TsTzSpan, TsTzSpanSet, Temporal, Box]) -> boo MEOS Functions: adjacent_span_span, adjacent_spanset_span """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, Temporal): return self.is_adjacent(other.time()) @@ -229,9 +222,7 @@ def is_adjacent(self, other: Union[TsTzSpan, TsTzSpanSet, Temporal, Box]) -> boo else: super().is_adjacent(other) - def is_contained_in( - self, container: Union[TsTzSpan, TsTzSpanSet, TsTzSet, Temporal, Box] - ) -> bool: + def is_contained_in(self, container: TsTzSpan | TsTzSpanSet | TsTzSet | Temporal | Box) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -253,8 +244,8 @@ def is_contained_in( contained_span_span, contained_span_spanset, contained_set_set, contained_spanset_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(container, Temporal): return self.is_contained_in(container.time()) @@ -263,7 +254,7 @@ def is_contained_in( else: return super().is_contained_in(container) - def contains(self, content: Union[datetime, TsTzSet, Temporal]) -> bool: + def contains(self, content: datetime | TsTzSet | Temporal) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -288,9 +279,7 @@ def contains(self, content: Union[datetime, TsTzSet, Temporal]) -> bool: from ...temporal import Temporal if isinstance(content, datetime): - return contains_set_timestamptz( - self._inner, datetime_to_timestamptz(content) - ) + return contains_set_timestamptz(self._inner, datetime_to_timestamptz(content)) elif isinstance(content, Temporal): return self.to_spanset().contains(content) else: @@ -320,9 +309,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps( - self, other: Union[TsTzSpan, TsTzSpanSet, TsTzSet, Temporal, Box] - ) -> bool: + def overlaps(self, other: TsTzSpan | TsTzSpanSet | TsTzSet | Temporal | Box) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -344,8 +331,8 @@ def overlaps( MEOS Functions: overlaps_set_set, overlaps_span_span, overlaps_spanset_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): return contains_set_timestamptz(self._inner, datetime_to_timestamptz(other)) @@ -356,7 +343,7 @@ def overlaps( else: return super().overlaps(other) - def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + def is_same(self, other: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` is the same as the bounding tstzspan of `other`. @@ -373,7 +360,7 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: return self.to_span().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[Time, Temporal, Box]) -> bool: + def is_left(self, other: Time | Temporal | Box) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -395,19 +382,17 @@ def is_left(self, other: Union[Time, Temporal, Box]) -> bool: MEOS Functions: overafter_timestamp_tstzspan, left_span_span, left_span_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): return after_timestamptz_set(datetime_to_timestamptz(other), self._inner) - elif isinstance(other, Temporal): - return self.to_span().is_left(other) - elif isinstance(other, get_args(Box)): + elif isinstance(other, (Temporal, get_args(Box))): return self.to_span().is_left(other) else: return super().is_left(other) - def is_over_or_left(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_left(self, other: Time | Temporal | Box) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -429,13 +414,11 @@ def is_over_or_left(self, other: Union[Time, Temporal, Box]) -> bool: MEOS Functions: overbefore_tstzspan_timestamp, overleft_span_span, overleft_span_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overafter_timestamptz_set( - datetime_to_timestamptz(other), self._inner - ) + return overafter_timestamptz_set(datetime_to_timestamptz(other), self._inner) elif isinstance(other, Temporal): return self.to_span().is_over_or_left(other) elif isinstance(other, get_args(Box)): @@ -443,7 +426,7 @@ def is_over_or_left(self, other: Union[Time, Temporal, Box]) -> bool: else: return super().is_over_or_left(other) - def is_over_or_right(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_right(self, other: Time | Temporal | Box) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same time). @@ -465,21 +448,17 @@ def is_over_or_right(self, other: Union[Time, Temporal, Box]) -> bool: MEOS Functions: overafter_tstzspan_timestamp, overright_span_span, overright_span_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overbefore_timestamptz_set( - datetime_to_timestamptz(other), self._inner - ) - elif isinstance(other, Temporal): - return self.to_span().is_over_or_right(other) - elif isinstance(other, get_args(Box)): + return overbefore_timestamptz_set(datetime_to_timestamptz(other), self._inner) + elif isinstance(other, (Temporal, get_args(Box))): return self.to_span().is_over_or_right(other) else: return super().is_over_or_right(other) - def is_right(self, other: Union[Time, Temporal, Box]) -> bool: + def is_right(self, other: Time | Temporal | Box) -> bool: """ Returns whether ``self`` is strictly after ``other``. That is, the first timestamp in ``self`` is after ``other``. @@ -502,20 +481,18 @@ def is_right(self, other: Union[Time, Temporal, Box]) -> bool: overbefore_timestamptz_set, right_set_set, right_span_span, right_span_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): return before_timestamptz_set(datetime_to_timestamptz(other), self._inner) - elif isinstance(other, Temporal): - return self.to_span().is_right(other) - elif isinstance(other, get_args(Box)): + elif isinstance(other, (Temporal, get_args(Box))): return self.to_span().is_right(other) else: return super().is_right(other) # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[Time, Temporal, Box]) -> timedelta: + def distance(self, other: Time | Temporal | Box) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -529,45 +506,33 @@ def distance(self, other: Union[Time, Temporal, Box]) -> timedelta: distance_set_timestamptz, distance_tstzset_tstzset, distance_tstzspanset_tstzspan, distance_tstzspanset_tstzspanset """ + from ...boxes import Box + from ...temporal import Temporal from .tstzspan import TsTzSpan from .tstzspanset import TsTzSpanSet - from ...temporal import Temporal - from ...boxes import Box if isinstance(other, datetime): - return timedelta( - seconds=distance_set_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) - ) + return timedelta(seconds=distance_set_timestamptz(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TsTzSet): - return timedelta( - seconds=distance_tstzset_tstzset(self._inner, other._inner) - ) - elif isinstance(other, TsTzSpan): - return self.to_spanset().distance(other) - elif isinstance(other, TsTzSpanSet): + return timedelta(seconds=distance_tstzset_tstzset(self._inner, other._inner)) + elif isinstance(other, (TsTzSpan, TsTzSpanSet)): return self.to_spanset().distance(other) - elif isinstance(other, Temporal): - return self.to_span().distance(other) - elif isinstance(other, get_args(Box)): + elif isinstance(other, (Temporal, get_args(Box))): return self.to_span().distance(other) else: return super().distance(other) # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: datetime) -> Optional[datetime]: ... + def intersection(self, other: datetime) -> datetime | None: ... @overload - def intersection(self, other: TsTzSet) -> Optional[TsTzSet]: ... + def intersection(self, other: TsTzSet) -> TsTzSet | None: ... @overload - def intersection( - self, other: Union[TsTzSpan, TsTzSpanSet, Temporal, Box] - ) -> Optional[TsTzSpanSet]: ... + def intersection(self, other: TsTzSpan | TsTzSpanSet | Temporal | Box) -> TsTzSpanSet | None: ... - def intersection(self, other: Union[Time, Temporal]) -> Optional[Time]: + def intersection(self, other: Time | Temporal) -> Time | None: """ Returns the temporal intersection of ``self`` and ``other``. @@ -585,16 +550,12 @@ def intersection(self, other: Union[Time, Temporal]) -> Optional[Time]: from .tstzspanset import TsTzSpanSet if isinstance(other, datetime): - result = intersection_set_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = intersection_set_timestamptz(self._inner, datetime_to_timestamptz(other)) return timestamptz_to_datetime(result) if result is not None else None elif isinstance(other, TsTzSet): result = intersection_set_set(self._inner, other._inner) return TsTzSet(_inner=result) if result is not None else None - elif isinstance(other, TsTzSpan): - return self.to_spanset().intersection(other) - elif isinstance(other, TsTzSpanSet): + elif isinstance(other, (TsTzSpan, TsTzSpanSet)): return self.to_spanset().intersection(other) elif isinstance(other, Temporal): return self.intersection(other.time()) @@ -604,14 +565,12 @@ def intersection(self, other: Union[Time, Temporal]) -> Optional[Time]: return super().intersection(other) @overload - def minus(self, other: Union[datetime, TsTzSet]) -> Optional[TsTzSet]: ... + def minus(self, other: datetime | TsTzSet) -> TsTzSet | None: ... @overload - def minus( - self, other: Union[TsTzSpan, TsTzSpanSet, Temporal, Box] - ) -> Optional[TsTzSpanSet]: ... + def minus(self, other: TsTzSpan | TsTzSpanSet | Temporal | Box) -> TsTzSpanSet | None: ... - def minus(self, other: Union[Time, Temporal, Box]) -> Optional[Time]: + def minus(self, other: Time | Temporal | Box) -> Time | None: """ Returns the temporal difference of ``self`` and ``other``. @@ -634,9 +593,7 @@ def minus(self, other: Union[Time, Temporal, Box]) -> Optional[Time]: elif isinstance(other, TsTzSet): result = minus_set_set(self._inner, other._inner) return TsTzSet(_inner=result) if result is not None else None - elif isinstance(other, TsTzSpan): - return self.to_spanset().minus(other) - elif isinstance(other, TsTzSpanSet): + elif isinstance(other, (TsTzSpan, TsTzSpanSet)): return self.to_spanset().minus(other) elif isinstance(other, Temporal): return self.minus(other.time()) @@ -645,7 +602,7 @@ def minus(self, other: Union[Time, Temporal, Box]) -> Optional[Time]: else: return super().minus(other) - def subtract_from(self, other: datetime) -> Optional[datetime]: + def subtract_from(self, other: datetime) -> datetime | None: """ Returns the difference of ``other`` and ``self``. @@ -661,19 +618,15 @@ def subtract_from(self, other: datetime) -> Optional[datetime]: See Also: :meth:`minus` """ - return timestamptz_to_datetime( - minus_timestamptz_set(datetime_to_timestamptz(other), self._inner) - ) + return timestamptz_to_datetime(minus_timestamptz_set(datetime_to_timestamptz(other), self._inner)) @overload - def union(self, other: Union[datetime, TsTzSet]) -> TsTzSet: ... + def union(self, other: datetime | TsTzSet) -> TsTzSet: ... @overload - def union( - self, other: Union[TsTzSpan, TsTzSpanSet, Temporal, Box] - ) -> TsTzSpanSet: ... + def union(self, other: TsTzSpan | TsTzSpanSet | Temporal | Box) -> TsTzSpanSet: ... - def union(self, other: Union[Time, Temporal, Box]) -> Union[TsTzSpanSet, TsTzSet]: + def union(self, other: Time | Temporal | Box) -> TsTzSpanSet | TsTzSet: """ Returns the temporal union of ``self`` and ``other``. @@ -691,16 +644,10 @@ def union(self, other: Union[Time, Temporal, Box]) -> Union[TsTzSpanSet, TsTzSet from .tstzspanset import TsTzSpanSet if isinstance(other, datetime): - return TsTzSet( - _inner=union_set_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) - ) + return TsTzSet(_inner=union_set_timestamptz(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TsTzSet): return TsTzSet(_inner=union_set_set(self._inner, other._inner)) - elif isinstance(other, TsTzSpan): - return self.to_spanset().union(other) - elif isinstance(other, TsTzSpanSet): + elif isinstance(other, (TsTzSpan, TsTzSpanSet)): return self.to_spanset().union(other) elif isinstance(other, Temporal): return self.union(other.time()) diff --git a/pymeos/collections/time/tstzspan.py b/pymeos/collections/time/tstzspan.py index feeaab14..faf501a3 100644 --- a/pymeos/collections/time/tstzspan.py +++ b/pymeos/collections/time/tstzspan.py @@ -1,20 +1,19 @@ from __future__ import annotations from datetime import datetime, timedelta -from typing import Optional, Union, overload, TYPE_CHECKING, get_args +from typing import TYPE_CHECKING, get_args, overload -from dateutil.parser import parse from pymeos_cffi import * -from .timecollection import TimeCollection from ..base.span import Span +from .timecollection import TimeCollection if TYPE_CHECKING: - from ...temporal import Temporal from ...boxes import Box - from .tstzspanset import TsTzSpanSet + from ...temporal import Temporal from .time import Time from .tstzset import TsTzSet + from .tstzspanset import TsTzSpanSet class TsTzSpan(Span[datetime], TimeCollection[datetime]): @@ -42,9 +41,7 @@ class TsTzSpan(Span[datetime], TimeCollection[datetime]): _mobilitydb_name = "tstzspan" _parse_function = tstzspan_in - _parse_value_function = lambda x: ( - pg_timestamptz_in(x, -1) if isinstance(x, str) else datetime_to_timestamptz(x) - ) + _parse_value_function = lambda x: (pg_timestamptz_in(x, -1) if isinstance(x, str) else datetime_to_timestamptz(x)) _make_function = tstzspan_make # ------------------------- Constructors ---------------------------------- @@ -157,9 +154,7 @@ def scale(self, duration: timedelta) -> TsTzSpan: """ return self.shift_scale(duration=duration) - def shift_scale( - self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None - ) -> TsTzSpan: + def shift_scale(self, shift: timedelta | None = None, duration: timedelta | None = None) -> TsTzSpan: """ Returns a new tstzspan that starts at ``self`` shifted by ``shift`` and has duration ``duration`` @@ -179,9 +174,7 @@ def shift_scale( MEOS Functions: tstzspan_shift_scale """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" modified = tstzspan_shift_scale( self._inner, timedelta_to_interval(shift) if shift else None, @@ -190,7 +183,7 @@ def shift_scale( return TsTzSpan(_inner=modified) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[Time, Box, Temporal]) -> bool: + def is_adjacent(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -213,13 +206,11 @@ def is_adjacent(self, other: Union[Time, Box, Temporal]) -> bool: adjacent_span_span, adjacent_span_spanset, adjacent_span_timestamptz, adjacent_span_tstzset, adjacent_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return adjacent_span_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return adjacent_span_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return adjacent_span_span(self._inner, temporal_to_tstzspan(other._inner)) elif isinstance(other, get_args(Box)): @@ -227,9 +218,7 @@ def is_adjacent(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_adjacent(other) - def is_contained_in( - self, container: Union[TsTzSpan, TsTzSpanSet, Box, Temporal] - ) -> bool: + def is_contained_in(self, container: TsTzSpan | TsTzSpanSet | Box | Temporal) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -250,8 +239,8 @@ def is_contained_in( MEOS Functions: contained_span_span, contained_span_spanset, contained_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(container, Temporal): return self.is_contained_in(container.tstzspan()) @@ -260,7 +249,7 @@ def is_contained_in( else: return super().is_contained_in(container) - def contains(self, content: Union[Time, Box, Temporal]) -> bool: + def contains(self, content: Time | Box | Temporal) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -282,13 +271,11 @@ def contains(self, content: Union[Time, Box, Temporal]) -> bool: contains_span_span, contains_span_spanset, contains_span_timestamptz, contains_span_tstzset, contains_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(content, datetime): - return contains_span_timestamptz( - self._inner, datetime_to_timestamptz(content) - ) + return contains_span_timestamptz(self._inner, datetime_to_timestamptz(content)) elif isinstance(content, Temporal): return self.contains(content.tstzspan()) elif isinstance(content, get_args(Box)): @@ -296,7 +283,7 @@ def contains(self, content: Union[Time, Box, Temporal]) -> bool: else: return super().contains(content) - def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: + def overlaps(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -319,13 +306,11 @@ def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: overlaps_span_span, overlaps_span_spanset, overlaps_span_tstzset, overlaps_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overlaps_span_span( - self._inner, timestamptz_to_span(datetime_to_timestamptz(other)) - ) + return overlaps_span_span(self._inner, timestamptz_to_span(datetime_to_timestamptz(other))) elif isinstance(other, Temporal): return self.overlaps(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -333,7 +318,7 @@ def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().overlaps(other) - def is_same(self, other: Union[Time, Box, Temporal]) -> bool: + def is_same(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` and the bounding tstzspan of ``other`` is the same. @@ -346,22 +331,20 @@ def is_same(self, other: Union[Time, Box, Temporal]) -> bool: MEOS Functions: same_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, Temporal): return self.is_same(other.tstzspan()) elif isinstance(other, get_args(Box)): return self.is_same(other.to_tstzspan()) elif isinstance(other, datetime): - return span_eq( - self._inner, timestamptz_to_span(datetime_to_timestamptz(other)) - ) + return span_eq(self._inner, timestamptz_to_span(datetime_to_timestamptz(other))) else: return super().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[Time, Box, Temporal]) -> bool: + def is_left(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -384,13 +367,11 @@ def is_left(self, other: Union[Time, Box, Temporal]) -> bool: left_span_span, left_span_spanset, before_span_timestamptz, before_span_tstzset, before_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overafter_timestamptz_span( - datetime_to_timestamptz(other), self._inner - ) + return overafter_timestamptz_span(datetime_to_timestamptz(other), self._inner) elif isinstance(other, Temporal): return self.is_left(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -398,7 +379,7 @@ def is_left(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_left(other) - def is_over_or_left(self, other: Union[Time, Box, Temporal]) -> bool: + def is_over_or_left(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -421,13 +402,11 @@ def is_over_or_left(self, other: Union[Time, Box, Temporal]) -> bool: overleft_span_span, overleft_span_spanset, overbefore_span_timestamptz, overbefore_span_tstzset, overbefore_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overbefore_span_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return overbefore_span_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return self.is_over_or_left(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -435,7 +414,7 @@ def is_over_or_left(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_over_or_left(other) - def is_right(self, other: Union[Time, Box, Temporal]) -> bool: + def is_right(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is strictly after ``other``. That is, ``self`` starts after ``other`` ends. @@ -458,13 +437,11 @@ def is_right(self, other: Union[Time, Box, Temporal]) -> bool: right_span_span, right_span_spanset, after_span_timestamptz, after_span_tstzset, after_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overbefore_timestamptz_span( - datetime_to_timestamptz(other), self._inner - ) + return overbefore_timestamptz_span(datetime_to_timestamptz(other), self._inner) elif isinstance(other, Temporal): return self.is_right(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -472,7 +449,7 @@ def is_right(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_right(other) - def is_over_or_right(self, other: Union[Time, Box, Temporal]) -> bool: + def is_over_or_right(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same time). @@ -495,13 +472,11 @@ def is_over_or_right(self, other: Union[Time, Box, Temporal]) -> bool: overright_span_span, overright_span_spanset, overafter_span_timestamptz, overafter_span_tstzset, overafter_span_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overafter_span_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return overafter_span_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return self.is_over_or_right(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -510,7 +485,7 @@ def is_over_or_right(self, other: Union[Time, Box, Temporal]) -> bool: return super().is_over_or_right(other) # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: + def distance(self, other: Time | Box | Temporal) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -524,27 +499,19 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: distance_span_timestamptz, distance_tstzspan_tstzspan, distance_tstzspanset_tstzspan """ + from ...boxes import Box + from ...temporal import Temporal from .tstzset import TsTzSet from .tstzspanset import TsTzSpanSet - from ...temporal import Temporal - from ...boxes import Box if isinstance(other, datetime): - return timedelta( - seconds=distance_span_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) - ) + return timedelta(seconds=distance_span_timestamptz(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TsTzSet): return self.distance(other.to_spanset()) elif isinstance(other, TsTzSpan): - return timedelta( - seconds=distance_tstzspan_tstzspan(self._inner, other._inner) - ) + return timedelta(seconds=distance_tstzspan_tstzspan(self._inner, other._inner)) elif isinstance(other, TsTzSpanSet): - return timedelta( - seconds=distance_tstzspanset_tstzspan(other._inner, self._inner) - ) + return timedelta(seconds=distance_tstzspanset_tstzspan(other._inner, self._inner)) elif isinstance(other, Temporal): return self.distance(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -554,17 +521,15 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: # ------------------------- Set Operations -------------------------------- @overload - def intersection(self, other: datetime) -> Optional[datetime]: ... + def intersection(self, other: datetime) -> datetime | None: ... @overload - def intersection(self, other: TsTzSpan) -> Optional[TsTzSpan]: ... + def intersection(self, other: TsTzSpan) -> TsTzSpan | None: ... @overload - def intersection( - self, other: Union[TsTzSet, TsTzSpanSet] - ) -> Optional[TsTzSpanSet]: ... + def intersection(self, other: TsTzSet | TsTzSpanSet) -> TsTzSpanSet | None: ... - def intersection(self, other: Time) -> Optional[Time]: + def intersection(self, other: Time) -> Time | None: """ Returns the temporal intersection of ``self`` and ``other``. @@ -578,13 +543,11 @@ def intersection(self, other: Time) -> Optional[Time]: intersection_span_span, intersection_spanset_span, intersection_span_timestamptz """ - from .tstzspanset import TsTzSpanSet from .tstzset import TsTzSet + from .tstzspanset import TsTzSpanSet if isinstance(other, datetime): - result = intersection_span_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = intersection_span_timestamptz(self._inner, datetime_to_timestamptz(other)) return timestamptz_to_datetime(result) if result is not None else None elif isinstance(other, TsTzSet): return self.intersection(other.to_tstzspanset()) @@ -610,8 +573,8 @@ def minus(self, other: Time) -> TsTzSpanSet: MEOS Functions: minus_span_timestamptz, minus_span_spanset, minus_span_span """ - from .tstzspanset import TsTzSpanSet from .tstzset import TsTzSet + from .tstzspanset import TsTzSpanSet if isinstance(other, datetime): result = minus_span_timestamptz(self._inner, datetime_to_timestamptz(other)) @@ -638,16 +601,12 @@ def union(self, other: Time) -> TsTzSpanSet: MEOS Functions: union_span_timestamptz, union_spanset_span, union_span_span """ - from .tstzspanset import TsTzSpanSet from .tstzset import TsTzSet + from .tstzspanset import TsTzSpanSet if isinstance(other, datetime): result = union_span_timestamptz(self._inner, datetime_to_timestamptz(other)) - elif isinstance(other, TsTzSet): - result = super().union(other) - elif isinstance(other, TsTzSpan): - result = super().union(other) - elif isinstance(other, TsTzSpanSet): + elif isinstance(other, (TsTzSet, TsTzSpan, TsTzSpanSet)): result = super().union(other) else: raise TypeError(f"Operation not supported with type {other.__class__}") diff --git a/pymeos/collections/time/tstzspanset.py b/pymeos/collections/time/tstzspanset.py index 95e91d2e..9e5f10fb 100644 --- a/pymeos/collections/time/tstzspanset.py +++ b/pymeos/collections/time/tstzspanset.py @@ -1,19 +1,18 @@ from __future__ import annotations -from datetime import timedelta, datetime -from typing import Optional, Union, List, overload, get_args -from typing import TYPE_CHECKING +from datetime import datetime, timedelta +from typing import TYPE_CHECKING, get_args, overload from pymeos_cffi import * from .timecollection import TimeCollection if TYPE_CHECKING: - from ...temporal import Temporal from ...boxes import Box - from .tstzspan import TsTzSpan - from .tstzset import TsTzSet + from ...temporal import Temporal from .time import Time + from .tstzset import TsTzSet + from .tstzspan import TsTzSpan from ..base.spanset import SpanSet @@ -87,7 +86,7 @@ def to_tstzspan(self) -> TsTzSpan: return self.to_span() # ------------------------- Accessors ------------------------------------- - def duration(self, ignore_gaps: Optional[bool] = False) -> timedelta: + def duration(self, ignore_gaps: bool | None = False) -> timedelta: """ Returns the duration of the tstzspanset. By default, i.e., when the second argument is False, the function takes into account the gaps within, @@ -207,7 +206,7 @@ def span_n(self, n: int) -> TsTzSpan: return TsTzSpan(_inner=super().span_n(n)) - def spans(self) -> List[TsTzSpan]: + def spans(self) -> list[TsTzSpan]: """ Returns the list of tstzspans in ``self``. Returns: @@ -263,9 +262,7 @@ def scale(self, duration: timedelta) -> TsTzSpanSet: """ return self.shift_scale(duration=duration) - def shift_scale( - self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None - ) -> TsTzSpanSet: + def shift_scale(self, shift: timedelta | None = None, duration: timedelta | None = None) -> TsTzSpanSet: """ Returns a new tstzspanset that starts at ``self`` shifted by ``shift`` and has duration ``duration`` @@ -285,9 +282,7 @@ def shift_scale( MEOS Functions: tstzspanset_shift_scale """ - assert ( - shift is not None or duration is not None - ), "shift and scale deltas must not be both None" + assert shift is not None or duration is not None, "shift and scale deltas must not be both None" ps = tstzspanset_shift_scale( self._inner, timedelta_to_interval(shift) if shift else None, @@ -296,7 +291,7 @@ def shift_scale( return TsTzSpanSet(_inner=ps) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[Time, Box, Temporal]) -> bool: + def is_adjacent(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -319,13 +314,11 @@ def is_adjacent(self, other: Union[Time, Box, Temporal]) -> bool: adjacent_spanset_span, adjacent_spanset_spanset, adjacent_spanset_timestamptz, adjacent_tstzspanset_tstzset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return adjacent_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return adjacent_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return self.is_adjacent(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -333,7 +326,7 @@ def is_adjacent(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_adjacent(other) - def is_contained_in(self, container: Union[Time, Box, Temporal]) -> bool: + def is_contained_in(self, container: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -355,13 +348,11 @@ def is_contained_in(self, container: Union[Time, Box, Temporal]) -> bool: contained_spanset_span, contained_spanset_spanset, contained_tstzspanset_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(container, datetime): - return contained_spanset_span( - self._inner, timestamptz_to_span(datetime_to_timestamptz(container)) - ) + return contained_spanset_span(self._inner, timestamptz_to_span(datetime_to_timestamptz(container))) elif isinstance(container, Temporal): return self.is_contained_in(container.tstzspan()) elif isinstance(container, get_args(Box)): @@ -369,7 +360,7 @@ def is_contained_in(self, container: Union[Time, Box, Temporal]) -> bool: else: return super().is_contained_in(container) - def contains(self, content: Union[Time, Box, Temporal]) -> bool: + def contains(self, content: Time | Box | Temporal) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -391,13 +382,11 @@ def contains(self, content: Union[Time, Box, Temporal]) -> bool: contains_spanset_span, contains_spanset_spanset, contains_spanset_timestamptz """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(content, datetime): - return contains_spanset_timestamptz( - self._inner, datetime_to_timestamptz(content) - ) + return contains_spanset_timestamptz(self._inner, datetime_to_timestamptz(content)) elif isinstance(content, Temporal): return self.contains(content.tstzspan()) elif isinstance(content, get_args(Box)): @@ -430,7 +419,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: + def overlaps(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -452,13 +441,11 @@ def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: MEOS Functions: overlaps_spanset_span, overlaps_spanset_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overlaps_spanset_span( - self._inner, timestamptz_to_span(datetime_to_timestamptz(other)) - ) + return overlaps_spanset_span(self._inner, timestamptz_to_span(datetime_to_timestamptz(other))) elif isinstance(other, Temporal): return self.overlaps(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -466,7 +453,7 @@ def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().overlaps(other) - def is_same(self, other: Union[Time, Box, Temporal]) -> bool: + def is_same(self, other: Time | Box | Temporal) -> bool: """ Returns whether the bounding tstzspan of `self` is the same as the bounding tstzspan of `other`. @@ -483,7 +470,7 @@ def is_same(self, other: Union[Time, Box, Temporal]) -> bool: return self.to_tstzspan().is_same(other) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[Time, Box, Temporal]) -> bool: + def is_left(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -505,13 +492,11 @@ def is_left(self, other: Union[Time, Box, Temporal]) -> bool: MEOS Functions: before_spanset_timestamptz, left_spanset_span, left_spanset_spanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return before_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return before_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return self.is_left(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -519,7 +504,7 @@ def is_left(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_left(other) - def is_over_or_left(self, other: Union[Time, Box, Temporal]) -> bool: + def is_over_or_left(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -543,13 +528,11 @@ def is_over_or_left(self, other: Union[Time, Box, Temporal]) -> bool: overbefore_spanset_timestamptz, overbefore_tstzspanset_tstzset, overbefore_tstzspanset_temporal """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overbefore_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return overbefore_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return self.is_over_or_left(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -557,7 +540,7 @@ def is_over_or_left(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_over_or_left(other) - def is_over_or_right(self, other: Union[Time, Box, Temporal]) -> bool: + def is_over_or_right(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same time). @@ -580,13 +563,11 @@ def is_over_or_right(self, other: Union[Time, Box, Temporal]) -> bool: overright_spanset_span, overright_spanset_spanset, overafter_spanset_timestamptz, overafter_tstzspanset_tstzset, """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overafter_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + return overafter_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, Temporal): return self.is_over_or_right(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -594,7 +575,7 @@ def is_over_or_right(self, other: Union[Time, Box, Temporal]) -> bool: else: return super().is_over_or_right(other) - def is_right(self, other: Union[Time, Box, Temporal]) -> bool: + def is_right(self, other: Time | Box | Temporal) -> bool: """ Returns whether ``self`` is strictly after ``other``.That is, ``self`` starts after ``other`` ends. @@ -617,13 +598,11 @@ def is_right(self, other: Union[Time, Box, Temporal]) -> bool: right_spanset_span, right_spanset_spanset, overbefore_timestamp_tstzspanset """ - from ...temporal import Temporal from ...boxes import Box + from ...temporal import Temporal if isinstance(other, datetime): - return overbefore_timestamptz_spanset( - datetime_to_timestamptz(other), self._inner - ) + return overbefore_timestamptz_spanset(datetime_to_timestamptz(other), self._inner) elif isinstance(other, Temporal): return self.is_right(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -632,7 +611,7 @@ def is_right(self, other: Union[Time, Box, Temporal]) -> bool: return super().is_right(other) # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: + def distance(self, other: Time | Box | Temporal) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -646,27 +625,19 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: distance_tstzspanset_tstzspan, distance_tstzspanset_tstzspanset, distance_spanset_timestamptz, distance_tstzspanset_tstzset """ + from ...boxes import Box + from ...temporal import Temporal from .tstzset import TsTzSet from .tstzspan import TsTzSpan - from ...temporal import Temporal - from ...boxes import Box if isinstance(other, datetime): - return timedelta( - seconds=distance_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) - ) + return timedelta(seconds=distance_spanset_timestamptz(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TsTzSet): return self.distance(other.to_spanset()) elif isinstance(other, TsTzSpan): - return timedelta( - seconds=distance_tstzspanset_tstzspan(self._inner, other._inner) - ) + return timedelta(seconds=distance_tstzspanset_tstzspan(self._inner, other._inner)) elif isinstance(other, TsTzSpanSet): - return timedelta( - seconds=distance_tstzspanset_tstzspanset(self._inner, other._inner) - ) + return timedelta(seconds=distance_tstzspanset_tstzspanset(self._inner, other._inner)) if isinstance(other, Temporal): return self.distance(other.tstzspan()) elif isinstance(other, get_args(Box)): @@ -684,7 +655,7 @@ def intersection(self, other: TsTzSpanSet) -> TsTzSpanSet: ... @overload def intersection(self, other: datetime) -> datetime: ... - def intersection(self, other: Time) -> Union[TsTzSpanSet, datetime, TsTzSet]: + def intersection(self, other: Time) -> TsTzSpanSet | datetime | TsTzSet: """ Returns the temporal intersection of ``self`` and ``other``. @@ -699,9 +670,7 @@ def intersection(self, other: Time) -> Union[TsTzSpanSet, datetime, TsTzSet]: intersection_spanset_span """ if isinstance(other, datetime): - result = intersection_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = intersection_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) return timestamptz_to_datetime(result) if result is not None else None else: result = super().intersection(other) @@ -737,9 +706,7 @@ def minus(self, other: Time) -> TsTzSpanSet: minus_spanset_span, minus_spanset_spanset, minus_spanset_timestamptz """ if isinstance(other, datetime): - result = minus_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = minus_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) else: result = super().minus(other) return TsTzSpanSet(_inner=result) if result is not None else None @@ -775,9 +742,7 @@ def union(self, other: Time) -> TsTzSpanSet: union_spanset_span """ if isinstance(other, datetime): - result = union_spanset_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = union_spanset_timestamptz(self._inner, datetime_to_timestamptz(other)) else: result = super().union(other) return TsTzSpanSet(_inner=result) if result is not None else None diff --git a/pymeos/db/asyncpg.py b/pymeos/db/asyncpg.py index dfab9bd2..ddc45530 100644 --- a/pymeos/db/asyncpg.py +++ b/pymeos/db/asyncpg.py @@ -39,6 +39,4 @@ async def register(cls, connection: asyncpg.connection.Connection) -> None: connection: An :class:`asyncpg.connection.Connection` to register the classes to. """ for cl in db_objects: - await connection.set_type_codec( - cl._mobilitydb_name, encoder=str, decoder=cl.read_from_cursor - ) + await connection.set_type_codec(cl._mobilitydb_name, encoder=str, decoder=cl.read_from_cursor) diff --git a/pymeos/db/db_objects.py b/pymeos/db/db_objects.py index c9084686..1759618e 100644 --- a/pymeos/db/db_objects.py +++ b/pymeos/db/db_objects.py @@ -1,24 +1,24 @@ from pymeos import ( + FloatSet, + FloatSpan, + FloatSpanSet, + GeographySet, + GeometrySet, + IntSet, + IntSpan, + IntSpanSet, + STBox, TBool, - TInt, + TBox, + TextSet, TFloat, - TText, - TGeomPoint, TGeogPoint, - TBox, - STBox, + TGeomPoint, + TInt, TsTzSet, TsTzSpan, TsTzSpanSet, - GeometrySet, - GeographySet, - TextSet, - IntSet, - IntSpan, - IntSpanSet, - FloatSpan, - FloatSet, - FloatSpanSet, + TText, ) db_objects = [ diff --git a/pymeos/db/psycopg.py b/pymeos/db/psycopg.py index 10233593..2cd8b618 100644 --- a/pymeos/db/psycopg.py +++ b/pymeos/db/psycopg.py @@ -2,7 +2,7 @@ import psycopg from psycopg import connect -from psycopg.adapt import Loader, Buffer, Dumper +from psycopg.adapt import Buffer, Dumper, Loader from .db_objects import db_objects diff --git a/pymeos/db/psycopg2.py b/pymeos/db/psycopg2.py index b2774ae4..887a9833 100644 --- a/pymeos/db/psycopg2.py +++ b/pymeos/db/psycopg2.py @@ -1,5 +1,5 @@ import psycopg2 -from psycopg2 import extensions, connect +from psycopg2 import connect, extensions from .db_objects import db_objects @@ -49,6 +49,4 @@ def register(cls, connection: psycopg2.extensions.connection) -> None: for cl in db_objects: cursor.execute(f"SELECT NULL::{cl._mobilitydb_name}") oid = cursor.description[0][1] - extensions.register_type( - extensions.new_type((oid,), cl._mobilitydb_name, cl.read_from_cursor) - ) + extensions.register_type(extensions.new_type((oid,), cl._mobilitydb_name, cl.read_from_cursor)) diff --git a/pymeos/factory.py b/pymeos/factory.py index 1bed983e..0f967af3 100644 --- a/pymeos/factory.py +++ b/pymeos/factory.py @@ -1,41 +1,41 @@ -from pymeos_cffi import MeosType, MeosTemporalSubtype +from pymeos_cffi import MeosTemporalSubtype, MeosType +from .collections import ( + DateSet, + DateSpan, + DateSpanSet, + FloatSet, + FloatSpan, + FloatSpanSet, + GeographySet, + GeometrySet, + IntSet, + IntSpan, + IntSpanSet, + TextSet, + TsTzSet, + TsTzSpan, + TsTzSpanSet, +) from .main import ( TBoolInst, TBoolSeq, TBoolSeqSet, - TIntInst, - TIntSeq, - TIntSeqSet, TFloatInst, TFloatSeq, TFloatSeqSet, - TTextInst, - TTextSeq, - TTextSeqSet, - TGeomPointInst, - TGeomPointSeq, - TGeomPointSeqSet, TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, -) -from .collections import ( - GeometrySet, - GeographySet, - IntSet, - IntSpan, - IntSpanSet, - FloatSet, - FloatSpan, - FloatSpanSet, - TextSet, - DateSet, - DateSpan, - DateSpanSet, - TsTzSet, - TsTzSpan, - TsTzSpanSet, + TGeomPointInst, + TGeomPointSeq, + TGeomPointSeqSet, + TIntInst, + TIntSeq, + TIntSeqSet, + TTextInst, + TTextSeq, + TTextSeqSet, ) @@ -128,9 +128,5 @@ def create_collection(inner): return None attributes = ["spansettype", "spantype", "settype"] - collection_type = next( - getattr(inner, attribute) - for attribute in attributes - if hasattr(inner, attribute) - ) + collection_type = next(getattr(inner, attribute) for attribute in attributes if hasattr(inner, attribute)) return _CollectionFactory._mapper[collection_type](_inner=inner) diff --git a/pymeos/main/__init__.py b/pymeos/main/__init__.py index b6517465..153e4cab 100644 --- a/pymeos/main/__init__.py +++ b/pymeos/main/__init__.py @@ -3,18 +3,18 @@ from .tint import TInt, TIntInst, TIntSeq, TIntSeqSet from .tnumber import TNumber from .tpoint import ( - TPoint, - TPointInst, - TPointSeq, - TPointSeqSet, - TGeomPoint, - TGeomPointInst, - TGeomPointSeq, - TGeomPointSeqSet, TGeogPoint, TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, + TGeomPoint, + TGeomPointInst, + TGeomPointSeq, + TGeomPointSeqSet, + TPoint, + TPointInst, + TPointSeq, + TPointSeqSet, ) from .ttext import TText, TTextInst, TTextSeq, TTextSeqSet diff --git a/pymeos/main/tbool.py b/pymeos/main/tbool.py index 6f9c1673..2ddacc92 100644 --- a/pymeos/main/tbool.py +++ b/pymeos/main/tbool.py @@ -1,12 +1,12 @@ from __future__ import annotations from abc import ABC -from typing import Optional, Union, List, Set, overload, Type, TypeVar +from typing import TypeVar, overload from pymeos_cffi import * from ..collections import * -from ..temporal import TInterpolation, Temporal, TInstant, TSequence, TSequenceSet +from ..temporal import Temporal, TInstant, TInterpolation, TSequence, TSequenceSet Self = TypeVar("Self", bound="TBool") @@ -50,7 +50,7 @@ def from_base_time(value: bool, base: datetime) -> TBoolInst: ... @staticmethod @overload - def from_base_time(value: bool, base: Union[TsTzSet, TsTzSpan]) -> TBoolSeq: ... + def from_base_time(value: bool, base: TsTzSet | TsTzSpan) -> TBoolSeq: ... @staticmethod @overload @@ -73,21 +73,17 @@ def from_base_time(value: bool, base: Time) -> TBool: tboolseq_from_base_tstzspan, tboolseqset_from_base_tstzspanset """ if isinstance(base, datetime): - return TBoolInst( - _inner=tboolinst_make(value, datetime_to_timestamptz(base)) - ) + return TBoolInst(_inner=tboolinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TsTzSet): return TBoolSeq(_inner=tboolseq_from_base_tstzset(value, base._inner)) elif isinstance(base, TsTzSpan): return TBoolSeq(_inner=tboolseq_from_base_tstzspan(value, base._inner)) elif isinstance(base, TsTzSpanSet): - return TBoolSeqSet( - _inner=tboolseqset_from_base_tstzspanset(value, base._inner) - ) + return TBoolSeqSet(_inner=tboolseqset_from_base_tstzspanset(value, base._inner)) raise TypeError(f"Operation not supported with type {base.__class__}") @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -124,7 +120,7 @@ def as_wkt(self): return tbool_out(self._inner) # ------------------------- Accessors ------------------------------------- - def value_set(self) -> Set[bool]: + def value_set(self) -> set[bool]: """ Returns the unique values in `self`. @@ -165,12 +161,10 @@ def value_at_timestamp(self, timestamp) -> bool: MEOS Function: tbool_value_at_timestamptz """ - return tbool_value_at_timestamptz( - self._inner, datetime_to_timestamptz(timestamp), True - ) + return tbool_value_at_timestamptz(self._inner, datetime_to_timestamptz(timestamp), True) # ------------------------- Ever and Always Comparisons ------------------- - def always_eq(self, value: Union[bool, TBool]) -> bool: + def always_eq(self, value: bool | TBool) -> bool: """ Returns whether `self` is always equal to `value`. @@ -190,7 +184,7 @@ def always_eq(self, value: Union[bool, TBool]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_eq(self, value: Union[bool, TBool]) -> bool: + def ever_eq(self, value: bool | TBool) -> bool: """ Returns whether `self` is ever equal to `value`. @@ -210,7 +204,7 @@ def ever_eq(self, value: Union[bool, TBool]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def never_eq(self, value: Union[bool, TBool]) -> bool: + def never_eq(self, value: bool | TBool) -> bool: """ Returns whether `self` is never equal to `value`. @@ -226,7 +220,7 @@ def never_eq(self, value: Union[bool, TBool]) -> bool: return not self.ever_eq(value) # ------------------------- Temporal Comparisons -------------------------- - def temporal_equal(self, other: Union[bool, TBool]) -> TBool: + def temporal_equal(self, other: bool | TBool) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -245,7 +239,7 @@ def temporal_equal(self, other: Union[bool, TBool]) -> TBool: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[bool, TBool]) -> TBool: + def temporal_not_equal(self, other: bool | TBool) -> TBool: """ Returns the temporal inequality relation between `self` and `other`. @@ -265,7 +259,7 @@ def temporal_not_equal(self, other: Union[bool, TBool]) -> TBool: return Temporal._factory(result) # ------------------------- Restrictions ---------------------------------- - def at(self, other: Union[bool, Time]) -> TBool: + def at(self, other: bool | Time) -> TBool: """ Returns a new temporal boolean with the values of `self` restricted to the time or value `other`. @@ -286,7 +280,7 @@ def at(self, other: Union[bool, Time]) -> TBool: return super().at(other) return Temporal._factory(result) - def minus(self, other: Union[bool, Time]) -> TBool: + def minus(self, other: bool | Time) -> TBool: """ Returns a new temporal boolean with the values of `self` restricted to the complement of the time or value @@ -310,7 +304,7 @@ def minus(self, other: Union[bool, Time]) -> TBool: return Temporal._factory(result) # ------------------------- Boolean Operations ---------------------------- - def temporal_and(self, other: Union[bool, TBool]) -> TBool: + def temporal_and(self, other: bool | TBool) -> TBool: """ Returns the temporal conjunction of `self` and `other`. @@ -345,7 +339,7 @@ def __and__(self, other): """ return self.temporal_and(other) - def temporal_or(self, other: Union[bool, TBool]) -> TBool: + def temporal_or(self, other: bool | TBool) -> TBool: """ Returns the temporal disjunction of `self` and `other`. @@ -415,7 +409,7 @@ def __invert__(self): """ return self.temporal_not() - def when_true(self) -> Optional[TsTzSpanSet]: + def when_true(self) -> TsTzSpanSet | None: """ Returns a tstzspan set with the tstzspans where `self` is True. @@ -428,7 +422,7 @@ def when_true(self) -> Optional[TsTzSpanSet]: result = tbool_when_true(self._inner) return TsTzSpanSet(_inner=result) if result is not None else None - def when_false(self) -> Optional[TsTzSpanSet]: + def when_false(self) -> TsTzSpanSet | None: """ Returns a tstzspan set with the tstzspans where `self` is False. @@ -473,10 +467,10 @@ class TBoolInst(TInstant[bool, "TBool", "TBoolInst", "TBoolSeq", "TBoolSeqSet"], def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - value: Optional[Union[str, bool]] = None, - timestamp: Optional[Union[str, datetime]] = None, + value: str | bool | None = None, + timestamp: str | datetime | None = None, _inner=None, ): super().__init__(string=string, value=value, timestamp=timestamp, _inner=_inner) @@ -491,9 +485,9 @@ class TBoolSeq(TSequence[bool, "TBool", "TBoolInst", "TBoolSeq", "TBoolSeqSet"], def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, TBoolInst]]] = None, + instant_list: list[str | TBoolInst] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.STEPWISE, @@ -511,9 +505,7 @@ def __init__( ) -class TBoolSeqSet( - TSequenceSet[bool, "TBool", "TBoolInst", "TBoolSeq", "TBoolSeqSet"], TBool -): +class TBoolSeqSet(TSequenceSet[bool, "TBool", "TBoolInst", "TBoolSeq", "TBoolSeqSet"], TBool): """ Class for representing temporal boolean values over a tstzspan of time with gaps. """ @@ -522,9 +514,9 @@ class TBoolSeqSet( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, TBoolSeq]]] = None, + sequence_list: list[str | TBoolSeq] | None = None, normalize: bool = True, _inner=None, ): diff --git a/pymeos/main/tfloat.py b/pymeos/main/tfloat.py index 6b6e56f6..242b3513 100644 --- a/pymeos/main/tfloat.py +++ b/pymeos/main/tfloat.py @@ -1,20 +1,19 @@ from __future__ import annotations from abc import ABC -from typing import Optional, List, Union, TYPE_CHECKING, Set, overload, Type, TypeVar +from typing import TYPE_CHECKING, TypeVar, overload from pymeos_cffi import * -from .tnumber import TNumber from ..collections import * from ..mixins import TSimplifiable, TTemporallyComparable -from ..temporal import TInterpolation, Temporal, TInstant, TSequence, TSequenceSet +from ..temporal import Temporal, TInstant, TInterpolation, TSequence, TSequenceSet +from .tnumber import TNumber if TYPE_CHECKING: from ..boxes import TBox - from .tint import TInt from .tbool import TBool - + from .tint import TInt Self = TypeVar("Self", bound="TFloat") @@ -28,6 +27,8 @@ class TFloat( _mobilitydb_name = "tfloat" BaseClass = float + DefaultInterpolation = TInterpolation.LINEAR + _parse_function = tfloat_in # ------------------------- Constructors ---------------------------------- @@ -57,32 +58,22 @@ def from_base_temporal( @staticmethod @overload - def from_base_time( - value: float, base: datetime, interpolation: None = None - ) -> TFloatInst: ... + def from_base_time(value: float, base: datetime, interpolation: None = None) -> TFloatInst: ... @staticmethod @overload - def from_base_time( - value: float, base: TsTzSet, interpolation: None = None - ) -> TFloatSeq: ... + def from_base_time(value: float, base: TsTzSet, interpolation: None = None) -> TFloatSeq: ... @staticmethod @overload - def from_base_time( - value: float, base: TsTzSpan, interpolation: TInterpolation = None - ) -> TFloatSeq: ... + def from_base_time(value: float, base: TsTzSpan, interpolation: TInterpolation = None) -> TFloatSeq: ... @staticmethod @overload - def from_base_time( - value: float, base: TsTzSpanSet, interpolation: TInterpolation = None - ) -> TFloatSeqSet: ... + def from_base_time(value: float, base: TsTzSpanSet, interpolation: TInterpolation = None) -> TFloatSeqSet: ... @staticmethod - def from_base_time( - value: float, base: Time, interpolation: TInterpolation = None - ) -> TFloat: + def from_base_time(value: float, base: Time, interpolation: TInterpolation = None) -> TFloat: """ Returns a new temporal float with the value `value` and the temporal frame of `base`. @@ -100,25 +91,17 @@ def from_base_time( tfloatseq_from_base_time, tfloatseqset_from_base_time """ if isinstance(base, datetime): - return TFloatInst( - _inner=tfloatinst_make(value, datetime_to_timestamptz(base)) - ) + return TFloatInst(_inner=tfloatinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TsTzSet): return TFloatSeq(_inner=tfloatseq_from_base_tstzset(value, base._inner)) elif isinstance(base, TsTzSpan): - return TFloatSeq( - _inner=tfloatseq_from_base_tstzspan(value, base._inner, interpolation) - ) + return TFloatSeq(_inner=tfloatseq_from_base_tstzspan(value, base._inner, interpolation)) elif isinstance(base, TsTzSpanSet): - return TFloatSeqSet( - _inner=tfloatseqset_from_base_tstzspanset( - value, base._inner, interpolation - ) - ) + return TFloatSeqSet(_inner=tfloatseqset_from_base_tstzspanset(value, base._inner, interpolation)) raise TypeError(f"Operation not supported with type {base.__class__}") @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -182,10 +165,7 @@ def to_tint(self) -> TInt: from ..factory import _TemporalFactory if self.interpolation() == TInterpolation.LINEAR: - raise ValueError( - "Cannot convert a temporal float with linear " - "interpolation to a temporal integer" - ) + raise ValueError("Cannot convert a temporal float with linear interpolation to a temporal integer") return _TemporalFactory.create_temporal(tfloat_to_tint(self._inner)) def to_floatrange(self) -> FloatSpan: @@ -249,7 +229,7 @@ def end_value(self) -> float: """ return tfloat_end_value(self._inner) - def value_set(self) -> Set[float]: + def value_set(self) -> set[float]: """ Returns the set of values of `self`. Note that when the interpolation is linear, the set will contain only @@ -289,7 +269,7 @@ def max_value(self) -> float: return tfloat_max_value(self._inner) # ------------------------- Ever and Always Comparisons ------------------- - def always_less(self, value: Union[float, TFloat]) -> bool: + def always_less(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are always less than `value`. @@ -310,7 +290,7 @@ def always_less(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_less_or_equal(self, value: Union[float, TFloat]) -> bool: + def always_less_or_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are always less than or equal to `value`. @@ -332,7 +312,7 @@ def always_less_or_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_equal(self, value: Union[float, TFloat]) -> bool: + def always_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are always equal to `value`. @@ -353,7 +333,7 @@ def always_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_not_equal(self, value: Union[float, TFloat]) -> bool: + def always_not_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are always not equal to `value`. @@ -374,7 +354,7 @@ def always_not_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_greater_or_equal(self, value: Union[float, TFloat]) -> bool: + def always_greater_or_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are always greater than or equal to `value`. @@ -396,7 +376,7 @@ def always_greater_or_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_greater(self, value: Union[float, TFloat]) -> bool: + def always_greater(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are always greater than `value`. @@ -417,7 +397,7 @@ def always_greater(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_less(self, value: Union[float, TFloat]) -> bool: + def ever_less(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are ever less than `value`. @@ -438,7 +418,7 @@ def ever_less(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_less_or_equal(self, value: Union[float, TFloat]) -> bool: + def ever_less_or_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are ever less than or equal to `value`. @@ -460,7 +440,7 @@ def ever_less_or_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_equal(self, value: Union[float, TFloat]) -> bool: + def ever_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are ever equal to `value`. @@ -481,7 +461,7 @@ def ever_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_not_equal(self, value: Union[float, TFloat]) -> bool: + def ever_not_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are ever not equal to `value`. @@ -502,7 +482,7 @@ def ever_not_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_greater_or_equal(self, value: Union[float, TFloat]) -> bool: + def ever_greater_or_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are ever greater than or equal to `value`. @@ -524,7 +504,7 @@ def ever_greater_or_equal(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_greater(self, value: Union[float, TFloat]) -> bool: + def ever_greater(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are ever greater than `value`. @@ -545,7 +525,7 @@ def ever_greater(self, value: Union[float, TFloat]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def never_less(self, value: Union[float, TFloat]) -> bool: + def never_less(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are never less than `value`. @@ -561,7 +541,7 @@ def never_less(self, value: Union[float, TFloat]) -> bool: """ return not self.ever_less(value) - def never_less_or_equal(self, value: Union[float, TFloat]) -> bool: + def never_less_or_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are never less than or equal to `value`. @@ -578,7 +558,7 @@ def never_less_or_equal(self, value: Union[float, TFloat]) -> bool: """ return not self.ever_less_or_equal(value) - def never_equal(self, value: Union[float, TFloat]) -> bool: + def never_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are never equal to `value`. @@ -594,7 +574,7 @@ def never_equal(self, value: Union[float, TFloat]) -> bool: """ return not self.ever_equal(value) - def never_not_equal(self, value: Union[float, TFloat]) -> bool: + def never_not_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are never not equal to `value`. @@ -610,7 +590,7 @@ def never_not_equal(self, value: Union[float, TFloat]) -> bool: """ return not self.ever_not_equal(value) - def never_greater_or_equal(self, value: Union[float, TFloat]) -> bool: + def never_greater_or_equal(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are never greater than or equal to `value`. @@ -627,7 +607,7 @@ def never_greater_or_equal(self, value: Union[float, TFloat]) -> bool: """ return not self.ever_greater_or_equal(value) - def never_greater(self, value: Union[float, TFloat]) -> bool: + def never_greater(self, value: float | TFloat) -> bool: """ Returns whether the values of `self` are never greater than `value`. @@ -644,7 +624,7 @@ def never_greater(self, value: Union[float, TFloat]) -> bool: return not self.ever_greater(value) # ------------------------- Temporal Comparisons -------------------------- - def temporal_equal(self, other: Union[int, float, TFloat]) -> TBool: + def temporal_equal(self, other: int | float | TFloat) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -658,13 +638,13 @@ def temporal_equal(self, other: Union[int, float, TFloat]) -> TBool: MEOS Functions: teq_tfloat_float, teq_temporal_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = teq_tfloat_float(self._inner, float(other)) else: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[int, float, TFloat]) -> TBool: + def temporal_not_equal(self, other: int | float | TFloat) -> TBool: """ Returns the temporal not equal relation between `self` and `other`. @@ -678,13 +658,13 @@ def temporal_not_equal(self, other: Union[int, float, TFloat]) -> TBool: MEOS Functions: tne_tfloat_float, tne_temporal_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tne_tfloat_float(self._inner, float(other)) else: return super().temporal_not_equal(other) return Temporal._factory(result) - def temporal_less(self, other: Union[int, float, TFloat]) -> TBool: + def temporal_less(self, other: int | float | TFloat) -> TBool: """ Returns the temporal less than relation between `self` and `other`. @@ -698,13 +678,13 @@ def temporal_less(self, other: Union[int, float, TFloat]) -> TBool: MEOS Functions: tlt_tfloat_float, tlt_temporal_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tlt_tfloat_float(self._inner, float(other)) else: return super().temporal_less(other) return Temporal._factory(result) - def temporal_less_or_equal(self, other: Union[int, float, TFloat]) -> TBool: + def temporal_less_or_equal(self, other: int | float | TFloat) -> TBool: """ Returns the temporal less or equal relation between `self` and `other`. @@ -719,13 +699,13 @@ def temporal_less_or_equal(self, other: Union[int, float, TFloat]) -> TBool: MEOS Functions: tle_tfloat_float, tle_temporal_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tle_tfloat_float(self._inner, float(other)) else: return super().temporal_less_or_equal(other) return Temporal._factory(result) - def temporal_greater_or_equal(self, other: Union[int, float, TFloat]) -> TBool: + def temporal_greater_or_equal(self, other: int | float | TFloat) -> TBool: """ Returns the temporal greater or equal relation between `self` and `other`. @@ -740,13 +720,13 @@ def temporal_greater_or_equal(self, other: Union[int, float, TFloat]) -> TBool: MEOS Functions: tge_tfloat_float, tge_temporal_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tge_tfloat_float(self._inner, float(other)) else: return super().temporal_greater_or_equal(other) return Temporal._factory(result) - def temporal_greater(self, other: Union[int, float, TFloat]) -> TBool: + def temporal_greater(self, other: int | float | TFloat) -> TBool: """ Returns the temporal greater than relation between `self` and `other`. @@ -761,7 +741,7 @@ def temporal_greater(self, other: Union[int, float, TFloat]) -> TBool: MEOS Functions: tgt_tfloat_float, tgt_temporal_temporal """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tgt_tfloat_float(self._inner, float(other)) else: return super().temporal_greater(other) @@ -770,18 +750,7 @@ def temporal_greater(self, other: Union[int, float, TFloat]) -> TBool: # ------------------------- Restrictions ---------------------------------- def at( self, - other: Union[ - float, - int, - FloatSet, - IntSet, - FloatSpan, - IntSpan, - FloatSpanSet, - IntSpanSet, - TBox, - Time, - ], + other: float | int | FloatSet | IntSet | FloatSpan | IntSpan | FloatSpanSet | IntSpanSet | TBox | Time, ) -> TFloat: """ Returns a new temporal float with the values of `self` restricted to @@ -798,7 +767,7 @@ def at( temporal_at_timestamp, temporal_at_tstzset, temporal_at_tstzspan, temporal_at_tstzspanset """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tfloat_at_value(self._inner, float(other)) elif isinstance(other, IntSet): return super().at(other.to_floatset()) @@ -812,18 +781,7 @@ def at( def minus( self, - other: Union[ - float, - int, - FloatSet, - IntSet, - FloatSpan, - IntSpan, - FloatSpanSet, - IntSpanSet, - TBox, - Time, - ], + other: float | int | FloatSet | IntSet | FloatSpan | IntSpan | FloatSpanSet | IntSpanSet | TBox | Time, ) -> Temporal: """ Returns a new temporal float with the values of `self` restricted to @@ -840,7 +798,7 @@ def minus( temporal_minus_timestamp, temporal_minus_tstzset, temporal_minus_tstzspan, temporal_minus_tstzspanset """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tfloat_minus_value(self._inner, float(other)) elif isinstance(other, IntSet): return super().minus(other.to_floatset()) @@ -865,9 +823,7 @@ def value_at_timestamp(self, timestamp) -> float: MEOS Functions: tfloat_value_at_timestamp """ - return tfloat_value_at_timestamptz( - self._inner, datetime_to_timestamptz(timestamp), True - ) + return tfloat_value_at_timestamptz(self._inner, datetime_to_timestamptz(timestamp), True) def derivative(self) -> TFloat: """ @@ -879,7 +835,7 @@ def derivative(self) -> TFloat: MEOS Functions: tfloat_derivative """ - return Temporal._factory(tfloat_derivative(self._inner)) + return Temporal._factory(temporal_derivative(self._inner)) # ------------------------- Transformations ---------------------------------- def to_degrees(self, normalize: bool = True) -> TFloat: @@ -923,10 +879,10 @@ def round(self, max_decimals: int = 0) -> TFloat: MEOS Functions: tfloat_round """ - return Temporal._factory(tfloat_round(self._inner, max_decimals)) + return Temporal._factory(temporal_round(self._inner, max_decimals)) # ------------------------- Split Operations ------------------------------ - def value_split(self, size: float, start: Optional[float] = 0) -> List[Temporal]: + def value_split(self, size: float, start: float | None = 0) -> list[Temporal]: """ Splits `self` into fragments with respect to value buckets @@ -946,10 +902,10 @@ def value_split(self, size: float, start: Optional[float] = 0) -> List[Temporal] def value_time_split( self, value_size: float, - duration: Union[str, timedelta], - value_start: Optional[float] = 0.0, - time_start: Optional[Union[str, datetime]] = None, - ) -> List[Temporal]: + duration: str | timedelta, + value_start: float | None = 0.0, + time_start: str | datetime | None = None, + ) -> list[Temporal]: """ Splits `self` into fragments with respect to value and tstzspan buckets. @@ -975,14 +931,8 @@ def value_time_split( if isinstance(time_start, datetime) else pg_timestamptz_in(time_start, -1) ) - dt = ( - timedelta_to_interval(duration) - if isinstance(duration, timedelta) - else pg_interval_in(duration, -1) - ) - fragments, _, _, count = tfloat_value_time_split( - self._inner, value_size, dt, value_start, st - ) + dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) else pg_interval_in(duration, -1) + fragments, _, _, count = tfloat_value_time_split(self._inner, value_size, dt, value_start, st) return [Temporal._factory(fragments[i]) for i in range(count)] # ------------------------- Database Operations --------------------------- @@ -1013,9 +963,7 @@ def read_from_cursor(value, _=None): raise Exception("ERROR: Could not parse temporal float value") -class TFloatInst( - TInstant[float, "TFloat", "TFloatInst", "TFloatSeq", "TFloatSeqSet"], TFloat -): +class TFloatInst(TInstant[float, "TFloat", "TFloatInst", "TFloatSeq", "TFloatSeqSet"], TFloat): """ Class for representing temporal floats at a single instant. """ @@ -1025,18 +973,16 @@ class TFloatInst( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - value: Optional[Union[str, float]] = None, - timestamp: Optional[Union[str, datetime]] = None, + value: str | float | None = None, + timestamp: str | datetime | None = None, _inner=None, ): super().__init__(string=string, value=value, timestamp=timestamp, _inner=_inner) -class TFloatSeq( - TSequence[float, "TFloat", "TFloatInst", "TFloatSeq", "TFloatSeqSet"], TFloat -): +class TFloatSeq(TSequence[float, "TFloat", "TFloatInst", "TFloatSeq", "TFloatSeqSet"], TFloat): """ Class for representing temporal floats over a tstzspan of time. """ @@ -1045,9 +991,9 @@ class TFloatSeq( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, TFloatInst]]] = None, + instant_list: list[str | TFloatInst] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.LINEAR, @@ -1065,9 +1011,7 @@ def __init__( ) -class TFloatSeqSet( - TSequenceSet[float, "TFloat", "TFloatInst", "TFloatSeq", "TFloatSeqSet"], TFloat -): +class TFloatSeqSet(TSequenceSet[float, "TFloat", "TFloatInst", "TFloatSeq", "TFloatSeqSet"], TFloat): """ Class for representing temporal floats over a tstzspan of time with gaps. """ @@ -1076,9 +1020,9 @@ class TFloatSeqSet( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, TFloatSeq]]] = None, + sequence_list: list[str | TFloatSeq] | None = None, normalize: bool = True, _inner=None, ): diff --git a/pymeos/main/tint.py b/pymeos/main/tint.py index f69e7f43..658e457e 100644 --- a/pymeos/main/tint.py +++ b/pymeos/main/tint.py @@ -1,19 +1,19 @@ from __future__ import annotations from abc import ABC -from typing import Optional, Union, List, TYPE_CHECKING, Set, overload, TypeVar, Type +from typing import TYPE_CHECKING, TypeVar, overload from pymeos_cffi import * -from .tnumber import TNumber from ..collections import * from ..mixins import TTemporallyComparable -from ..temporal import TInterpolation, Temporal, TInstant, TSequence, TSequenceSet +from ..temporal import Temporal, TInstant, TInterpolation, TSequence, TSequenceSet +from .tnumber import TNumber if TYPE_CHECKING: from ..boxes import TBox - from .tfloat import TFloat from .tbool import TBool + from .tfloat import TFloat Self = TypeVar("Self", bound="TInt") @@ -55,7 +55,7 @@ def from_base_time(value: int, base: datetime) -> TIntInst: ... @staticmethod @overload - def from_base_time(value: int, base: Union[TsTzSet, TsTzSpan]) -> TIntSeq: ... + def from_base_time(value: int, base: TsTzSet | TsTzSpan) -> TIntSeq: ... @staticmethod @overload @@ -85,13 +85,11 @@ def from_base_time(value: int, base: Time) -> TInt: elif isinstance(base, TsTzSpan): return TIntSeq(_inner=tintseq_from_base_tstzspan(value, base._inner)) elif isinstance(base, TsTzSpanSet): - return TIntSeqSet( - _inner=tintseqset_from_base_tstzspanset(value, base._inner) - ) + return TIntSeqSet(_inner=tintseqset_from_base_tstzspanset(value, base._inner)) raise TypeError(f"Operation not supported with type {base.__class__}") @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -209,7 +207,7 @@ def end_value(self) -> int: """ return tint_end_value(self._inner) - def value_set(self) -> Set[int]: + def value_set(self) -> set[int]: """ Returns the set of values of `self`. @@ -259,12 +257,10 @@ def value_at_timestamp(self, timestamp) -> int: MEOS Functions: tint_value_at_timestamp """ - return tint_value_at_timestamptz( - self._inner, datetime_to_timestamptz(timestamp), True - ) + return tint_value_at_timestamptz(self._inner, datetime_to_timestamptz(timestamp), True) # ------------------------- Ever and Always Comparisons ------------------- - def always_less(self, value: Union[int, TInt]) -> bool: + def always_less(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are always less than `value`. @@ -285,7 +281,7 @@ def always_less(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_less_or_equal(self, value: Union[int, TInt]) -> bool: + def always_less_or_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are always less than or equal to `value`. @@ -307,7 +303,7 @@ def always_less_or_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_equal(self, value: Union[int, TInt]) -> bool: + def always_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are always equal to `value`. @@ -328,7 +324,7 @@ def always_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_not_equal(self, value: Union[int, TInt]) -> bool: + def always_not_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are always not equal to `value`. @@ -349,7 +345,7 @@ def always_not_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_greater_or_equal(self, value: Union[int, TInt]) -> bool: + def always_greater_or_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are always greater than or equal to `value`. @@ -371,7 +367,7 @@ def always_greater_or_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_greater(self, value: Union[int, TInt]) -> bool: + def always_greater(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are always greater than `value`. @@ -392,7 +388,7 @@ def always_greater(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_less(self, value: Union[int, TInt]) -> bool: + def ever_less(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are ever less than `value`. @@ -413,7 +409,7 @@ def ever_less(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_less_or_equal(self, value: Union[int, TInt]) -> bool: + def ever_less_or_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are ever less than or equal to `value`. @@ -435,7 +431,7 @@ def ever_less_or_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_equal(self, value: Union[int, TInt]) -> bool: + def ever_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are ever equal to `value`. @@ -456,7 +452,7 @@ def ever_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_not_equal(self, value: Union[int, TInt]) -> bool: + def ever_not_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are ever not equal to `value`. @@ -477,7 +473,7 @@ def ever_not_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_greater_or_equal(self, value: Union[int, TInt]) -> bool: + def ever_greater_or_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are ever greater than or equal to `value`. @@ -499,7 +495,7 @@ def ever_greater_or_equal(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_greater(self, value: Union[int, TInt]) -> bool: + def ever_greater(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are ever greater than `value`. @@ -520,7 +516,7 @@ def ever_greater(self, value: Union[int, TInt]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def never_less(self, value: Union[int, TInt]) -> bool: + def never_less(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are never less than `value`. @@ -536,7 +532,7 @@ def never_less(self, value: Union[int, TInt]) -> bool: """ return not self.ever_less(value) - def never_less_or_equal(self, value: Union[int, TInt]) -> bool: + def never_less_or_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are never less than or equal to `value`. @@ -553,7 +549,7 @@ def never_less_or_equal(self, value: Union[int, TInt]) -> bool: """ return not self.ever_less_or_equal(value) - def never_equal(self, value: Union[int, TInt]) -> bool: + def never_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are never equal to `value`. @@ -569,7 +565,7 @@ def never_equal(self, value: Union[int, TInt]) -> bool: """ return not self.ever_equal(value) - def never_not_equal(self, value: Union[int, TInt]) -> bool: + def never_not_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are never not equal to `value`. @@ -585,7 +581,7 @@ def never_not_equal(self, value: Union[int, TInt]) -> bool: """ return not self.ever_not_equal(value) - def never_greater_or_equal(self, value: Union[int, TInt]) -> bool: + def never_greater_or_equal(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are never greater than or equal to `value`. @@ -602,7 +598,7 @@ def never_greater_or_equal(self, value: Union[int, TInt]) -> bool: """ return not self.ever_greater_or_equal(value) - def never_greater(self, value: Union[int, TInt]) -> bool: + def never_greater(self, value: int | TInt) -> bool: """ Returns whether the values of `self` are never greater than `value`. @@ -619,7 +615,7 @@ def never_greater(self, value: Union[int, TInt]) -> bool: return not self.ever_greater(value) # ------------------------- Temporal Comparisons -------------------------- - def temporal_equal(self, other: Union[int, TInt]) -> TBool: + def temporal_equal(self, other: int | TInt) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -638,7 +634,7 @@ def temporal_equal(self, other: Union[int, TInt]) -> TBool: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[int, TInt]) -> TBool: + def temporal_not_equal(self, other: int | TInt) -> TBool: """ Returns the temporal not equal relation between `self` and `other`. @@ -657,7 +653,7 @@ def temporal_not_equal(self, other: Union[int, TInt]) -> TBool: return super().temporal_not_equal(other) return Temporal._factory(result) - def temporal_less(self, other: Union[int, TInt]) -> TBool: + def temporal_less(self, other: int | TInt) -> TBool: """ Returns the temporal less than relation between `self` and `other`. @@ -676,7 +672,7 @@ def temporal_less(self, other: Union[int, TInt]) -> TBool: return super().temporal_less(other) return Temporal._factory(result) - def temporal_less_or_equal(self, other: Union[int, TInt]) -> TBool: + def temporal_less_or_equal(self, other: int | TInt) -> TBool: """ Returns the temporal less or equal relation between `self` and `other`. @@ -696,7 +692,7 @@ def temporal_less_or_equal(self, other: Union[int, TInt]) -> TBool: return super().temporal_less_or_equal(other) return Temporal._factory(result) - def temporal_greater_or_equal(self, other: Union[int, TInt]) -> TBool: + def temporal_greater_or_equal(self, other: int | TInt) -> TBool: """ Returns the temporal greater or equal relation between `self` and `other`. @@ -716,7 +712,7 @@ def temporal_greater_or_equal(self, other: Union[int, TInt]) -> TBool: return super().temporal_greater_or_equal(other) return Temporal._factory(result) - def temporal_greater(self, other: Union[int, TInt]) -> TBool: + def temporal_greater(self, other: int | TInt) -> TBool: """ Returns the temporal greater than relation between `self` and `other`. @@ -739,18 +735,7 @@ def temporal_greater(self, other: Union[int, TInt]) -> TBool: # ------------------------- Restrictions ---------------------------------- def at( self, - other: Union[ - int, - float, - IntSet, - FloatSet, - IntSpan, - FloatSpan, - IntSpanSet, - FloatSpanSet, - TBox, - Time, - ], + other: int | float | IntSet | FloatSet | IntSpan | FloatSpan | IntSpanSet | FloatSpanSet | TBox | Time, ) -> TInt: """ Returns a new temporal int with th e values of `self` restricted to @@ -767,7 +752,7 @@ def at( temporal_at_timestamp, temporal_at_tstzset, temporal_at_tstzspan, temporal_at_tstzspanset """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tint_at_value(self._inner, int(other)) elif isinstance(other, FloatSet): return super().at(other.to_intset()) @@ -781,18 +766,7 @@ def at( def minus( self, - other: Union[ - int, - float, - IntSet, - FloatSet, - IntSpan, - FloatSpan, - IntSpanSet, - FloatSpanSet, - TBox, - Time, - ], + other: int | float | IntSet | FloatSet | IntSpan | FloatSpan | IntSpanSet | FloatSpanSet | TBox | Time, ) -> TInt: """ Returns a new temporal int with the values of `self` restricted to the @@ -809,7 +783,7 @@ def minus( temporal_minus_timestamp, temporal_minus_tstzset, temporal_minus_tstzspan, temporal_minus_tstzspanset """ - if isinstance(other, int) or isinstance(other, float): + if isinstance(other, (int, float)): result = tint_minus_value(self._inner, int(other)) elif isinstance(other, FloatSet): return super().minus(other.to_intset()) @@ -822,9 +796,7 @@ def minus( return Temporal._factory(result) # ------------------------- Distance -------------------------------------- - def nearest_approach_distance( - self, other: Union[int, float, TNumber, TBox] - ) -> float: + def nearest_approach_distance(self, other: int | float | TNumber | TBox) -> float: """ Returns the nearest approach distance between `self` and `other`. @@ -847,7 +819,7 @@ def nearest_approach_distance( return super().nearest_approach_distance(other) # ------------------------- Split Operations ------------------------------ - def value_split(self, size: int, start: Optional[int] = 0) -> List[TInt]: + def value_split(self, size: int, start: int | None = 0) -> list[TInt]: """ Splits `self` into fragments with respect to value buckets @@ -867,10 +839,10 @@ def value_split(self, size: int, start: Optional[int] = 0) -> List[TInt]: def value_time_split( self, value_size: int, - duration: Union[str, timedelta], - value_start: Optional[int] = 0, - time_start: Optional[Union[str, datetime]] = None, - ) -> List[TInt]: + duration: str | timedelta, + value_start: int | None = 0, + time_start: str | datetime | None = None, + ) -> list[TInt]: """ Splits `self` into fragments with respect to value and tstzspan buckets. @@ -896,14 +868,8 @@ def value_time_split( if isinstance(time_start, datetime) else pg_timestamptz_in(time_start, -1) ) - dt = ( - timedelta_to_interval(duration) - if isinstance(duration, timedelta) - else pg_interval_in(duration, -1) - ) - tiles, _, _, count = tint_value_time_split( - self._inner, value_size, dt, value_start, st - ) + dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) else pg_interval_in(duration, -1) + tiles, _, _, count = tint_value_time_split(self._inner, value_size, dt, value_start, st) return [Temporal._factory(tiles[i]) for i in range(count)] # ------------------------- Database Operations --------------------------- @@ -938,10 +904,10 @@ class TIntInst(TInstant[int, "TInt", "TIntInst", "TIntSeq", "TIntSeqSet"], TInt) def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - value: Optional[Union[str, int]] = None, - timestamp: Optional[Union[str, datetime]] = None, + value: str | int | None = None, + timestamp: str | datetime | None = None, _inner=None, ): super().__init__(string=string, value=value, timestamp=timestamp, _inner=_inner) @@ -956,9 +922,9 @@ class TIntSeq(TSequence[int, "TInt", "TIntInst", "TIntSeq", "TIntSeqSet"], TInt) def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, TIntInst]]] = None, + instant_list: list[str | TIntInst] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.STEPWISE, @@ -985,9 +951,9 @@ class TIntSeqSet(TSequenceSet[int, "TInt", "TIntInst", "TIntSeq", "TIntSeqSet"], def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, TIntSeq]]] = None, + sequence_list: list[str | TIntSeq] | None = None, normalize: bool = True, _inner=None, ): diff --git a/pymeos/main/tnumber.py b/pymeos/main/tnumber.py index 4047c772..c8e33e42 100644 --- a/pymeos/main/tnumber.py +++ b/pymeos/main/tnumber.py @@ -1,17 +1,16 @@ from __future__ import annotations from abc import ABC -from typing import Union, TYPE_CHECKING, TypeVar +from typing import TYPE_CHECKING, TypeVar from pymeos_cffi import * -from ..collections import IntSet, FloatSet +from ..collections import FloatSet, IntSet from ..temporal import Temporal if TYPE_CHECKING: from ..boxes import Box, TBox - from ..collections import Time, IntSpan, IntSpanSet, FloatSpan, FloatSpanSet - from .tint import TInt + from ..collections import FloatSpan, FloatSpanSet, IntSpan, IntSpanSet, Time from .tfloat import TFloat TBase = TypeVar("TBase", int, float) @@ -63,7 +62,7 @@ def time_weighted_average(self) -> float: return tnumber_twavg(self._inner) # ------------------------- Transformations ------------------------------- - def shift_value(self: Self, delta: Union[int, float]) -> Self: + def shift_value(self: Self, delta: int | float) -> Self: """ Returns a new :class:`TNumber` with the value dimension shifted by ``delta``. @@ -74,8 +73,8 @@ def shift_value(self: Self, delta: Union[int, float]) -> Self: MEOS Functions: tint_shift_value, tfloat_shift_value """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt): shifted = tint_shift_value(self._inner, int(delta)) @@ -85,7 +84,7 @@ def shift_value(self: Self, delta: Union[int, float]) -> Self: raise TypeError(f"Operation not supported with type {self.__class__}") return Temporal._factory(shifted) - def scale_value(self: Self, width: Union[int, float]) -> Self: + def scale_value(self: Self, width: int | float) -> Self: """ Returns a new :class:`TNumber` scaled so the value dimension has width ``width``. @@ -96,8 +95,8 @@ def scale_value(self: Self, width: Union[int, float]) -> Self: MEOS Functions: tint_scale_value, tfloat_scale_value """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt): scaled = tint_scale_value(self._inner, int(width)) @@ -107,9 +106,7 @@ def scale_value(self: Self, width: Union[int, float]) -> Self: raise TypeError(f"Operation not supported with type {self.__class__}") return Temporal._factory(scaled) - def shift_scale_value( - self: Self, shift: Union[int, float] = None, width: Union[int, float] = None - ) -> Self: + def shift_scale_value(self: Self, shift: int | float = None, width: int | float = None) -> Self: """ Returns a new :class:`TNumber` with the value dimension shifted by ``shift`` and scaled so the value dimension has width ``width``. @@ -121,12 +118,10 @@ def shift_scale_value( MEOS Functions: tint_shift_scale_value, tfloat_shift_scale_value """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt - assert ( - shift is not None or width is not None - ), "shift and width must not be both None" + assert shift is not None or width is not None, "shift and width must not be both None" if isinstance(self, TInt): scaled = tint_shift_scale_value( @@ -147,9 +142,7 @@ def shift_scale_value( # ------------------------- Restrictions ---------------------------------- def at( self, - other: Union[ - IntSet, FloatSet, IntSpan, FloatSpan, IntSpanSet, FloatSpanSet, TBox, Time - ], + other: IntSet | FloatSet | IntSpan | FloatSpan | IntSpanSet | FloatSpanSet | TBox | Time, ) -> TG: """ Returns a new temporal object with the values of `self` restricted to @@ -168,19 +161,19 @@ def at( """ from ..boxes import TBox from ..collections import ( - IntSet, FloatSet, - IntSpan, FloatSpan, - IntSpanSet, FloatSpanSet, + IntSet, + IntSpan, + IntSpanSet, ) - if isinstance(other, IntSet) or isinstance(other, FloatSet): + if isinstance(other, (IntSet, FloatSet)): result = temporal_at_values(self._inner, other._inner) - elif isinstance(other, IntSpan) or isinstance(other, FloatSpan): + elif isinstance(other, (IntSpan, FloatSpan)): result = tnumber_at_span(self._inner, other._inner) - elif isinstance(other, IntSpanSet) or isinstance(other, FloatSpanSet): + elif isinstance(other, (IntSpanSet, FloatSpanSet)): result = tnumber_at_spanset(self._inner, other._inner) elif isinstance(other, TBox): result = tnumber_at_tbox(self._inner, other._inner) @@ -190,9 +183,7 @@ def at( def minus( self, - other: Union[ - IntSet, FloatSet, IntSpan, FloatSpan, IntSpanSet, FloatSpanSet, TBox, Time - ], + other: IntSet | FloatSet | IntSpan | FloatSpan | IntSpanSet | FloatSpanSet | TBox | Time, ) -> TG: """ Returns a new temporal object with the values of `self` restricted to @@ -212,19 +203,19 @@ def minus( """ from ..boxes import TBox from ..collections import ( - IntSet, FloatSet, - IntSpan, FloatSpan, - IntSpanSet, FloatSpanSet, + IntSet, + IntSpan, + IntSpanSet, ) - if isinstance(other, IntSet) or isinstance(other, FloatSet): + if isinstance(other, (IntSet, FloatSet)): result = temporal_minus_values(self._inner, other._inner) - elif isinstance(other, IntSpan) or isinstance(other, FloatSpan): + elif isinstance(other, (IntSpan, FloatSpan)): result = tnumber_minus_span(self._inner, other._inner) - elif isinstance(other, IntSpanSet) or isinstance(other, FloatSpanSet): + elif isinstance(other, (IntSpanSet, FloatSpanSet)): result = tnumber_minus_spanset(self._inner, other._inner) elif isinstance(other, TBox): result = tnumber_minus_tbox(self._inner, other._inner) @@ -233,7 +224,7 @@ def minus( return Temporal._factory(result) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[Temporal, Box]) -> bool: + def is_left(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is left to the bounding box of `other`. @@ -249,7 +240,7 @@ def is_left(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_left(other) - def is_over_or_left(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_left(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or left to the bounding box of `other`. @@ -265,7 +256,7 @@ def is_over_or_left(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_over_or_left(other) - def is_right(self, other: Union[Temporal, Box]) -> bool: + def is_right(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is right to the bounding box of `other`. @@ -281,7 +272,7 @@ def is_right(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_right(other) - def is_over_or_right(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_right(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or right to the bounding box of `other`. @@ -298,7 +289,7 @@ def is_over_or_right(self, other: Union[Temporal, Box]) -> bool: return self.bounding_box().is_over_or_right(other) # ------------------------- Mathematical Operations ------------------------- - def add(self, other: Union[int, float, TNumber]) -> TNumber: + def add(self, other: int | float | TNumber) -> TNumber: """ Returns a new temporal object with the values of `self` plus `other`. @@ -309,8 +300,8 @@ def add(self, other: Union[int, float, TNumber]) -> TNumber: Returns: A new temporal object of the same subtype as `self`. """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = add_tint_int(self._inner, other) @@ -322,7 +313,7 @@ def add(self, other: Union[int, float, TNumber]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def radd(self, other: Union[int, float]) -> TNumber: + def radd(self, other: int | float) -> TNumber: """ Returns a new temporal object with the values of `self` plus `other`. @@ -335,8 +326,8 @@ def radd(self, other: Union[int, float]) -> TNumber: MEOS Functions: add_int_tint, add_float_tfloat """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = add_int_tint(other, self._inner) @@ -346,7 +337,7 @@ def radd(self, other: Union[int, float]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def sub(self, other: Union[int, float, TNumber]) -> TNumber: + def sub(self, other: int | float | TNumber) -> TNumber: """ Returns a new temporal object with the values of `self` minus `other`. @@ -360,8 +351,8 @@ def sub(self, other: Union[int, float, TNumber]) -> TNumber: MEOS Functions: sub_tint_int, sub_tfloat_float, sub_tnumber_tnumber """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = sub_tint_int(self._inner, other) @@ -373,7 +364,7 @@ def sub(self, other: Union[int, float, TNumber]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def rsub(self, other: Union[int, float]) -> TNumber: + def rsub(self, other: int | float) -> TNumber: """ Returns a new temporal object with the values of `other` minus `self`. @@ -386,8 +377,8 @@ def rsub(self, other: Union[int, float]) -> TNumber: MEOS Functions: sub_int_tint, sub_float_tfloat """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = sub_int_tint(other, self._inner) @@ -397,7 +388,7 @@ def rsub(self, other: Union[int, float]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def mul(self, other: Union[int, float, TNumber]) -> TNumber: + def mul(self, other: int | float | TNumber) -> TNumber: """ Returns a new temporal object with the values of `self` multiplied by `other`. @@ -412,8 +403,8 @@ def mul(self, other: Union[int, float, TNumber]) -> TNumber: MEOS Functions: mult_tint_int, mult_tfloat_float, mult_tnumber_tnumber """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = mult_tint_int(self._inner, other) @@ -425,7 +416,7 @@ def mul(self, other: Union[int, float, TNumber]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def rmul(self, other: Union[int, float]) -> TNumber: + def rmul(self, other: int | float) -> TNumber: """ Returns a new temporal object with the values of `self` multiplied by `other`. @@ -439,8 +430,8 @@ def rmul(self, other: Union[int, float]) -> TNumber: MEOS Functions: mult_int_tint, mult_float_tfloat """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = mult_int_tint(other, self._inner) @@ -450,7 +441,7 @@ def rmul(self, other: Union[int, float]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def div(self, other: Union[int, float, TNumber]) -> TNumber: + def div(self, other: int | float | TNumber) -> TNumber: """ Returns a new temporal object with the values of `self` divided by `other`. @@ -465,8 +456,8 @@ def div(self, other: Union[int, float, TNumber]) -> TNumber: MEOS Functions: div_tint_int, div_tfloat_float, div_tnumber_tnumber """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = div_tint_int(self._inner, other) @@ -478,7 +469,7 @@ def div(self, other: Union[int, float, TNumber]) -> TNumber: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def rdiv(self, other: Union[int, float]) -> TNumber: + def rdiv(self, other: int | float) -> TNumber: """ Returns a new temporal object with the values of `other` divided by `self`. @@ -492,8 +483,8 @@ def rdiv(self, other: Union[int, float]) -> TNumber: MEOS Functions: div_int_tint, div_float_tfloat """ - from .tint import TInt from .tfloat import TFloat + from .tint import TInt if isinstance(self, TInt) and isinstance(other, int): result = div_int_tint(other, self._inner) @@ -657,7 +648,7 @@ def delta_value(self) -> TNumber: return _TemporalFactory.create_temporal(tnumber_delta_value(self._inner)) # ------------------------- Distance Operations -------------------------- - def distance(self, other: Union[int, float, TNumber]) -> TFloat: + def distance(self, other: int | float | TNumber) -> TFloat: """ Returns the temporal distance between `self` and `other`. @@ -681,9 +672,7 @@ def distance(self, other: Union[int, float, TNumber]) -> TFloat: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def nearest_approach_distance( - self, other: Union[int, float, TNumber, TBox] - ) -> float: + def nearest_approach_distance(self, other: int | float | TNumber | TBox) -> float: """ Returns the nearest approach distance between `self` and `other`. diff --git a/pymeos/main/tpoint.py b/pymeos/main/tpoint.py index 6bc22d9e..9ae1441b 100644 --- a/pymeos/main/tpoint.py +++ b/pymeos/main/tpoint.py @@ -2,14 +2,8 @@ from abc import ABC from typing import ( - Optional, - List, TYPE_CHECKING, - Set, - Tuple, - Union, TypeVar, - Type, overload, ) @@ -17,16 +11,17 @@ import shapely.geometry.base as shpb from pymeos_cffi import * -from .tbool import TBool -from .tfloat import TFloat, TFloatInst, TFloatSeq, TFloatSeqSet from ..collections import * from ..mixins import TSimplifiable -from ..temporal import Temporal, TInstant, TSequence, TSequenceSet, TInterpolation +from ..temporal import Temporal, TInstant, TInterpolation, TSequence, TSequenceSet +from .tbool import TBool +from .tfloat import TFloat, TFloatInst, TFloatSeq, TFloatSeqSet if TYPE_CHECKING: - from ..boxes import STBox, Box from geopandas import GeoDataFrame + from ..boxes import Box, STBox + def import_geopandas(): try: @@ -51,14 +46,14 @@ class TPoint(Temporal[shp.Point, TG, TI, TS, TSS], TSimplifiable, ABC): Abstract class for temporal points. """ - _projection_cache: dict[tuple[int, int], "LWPROJ"] = {} + DefaultInterpolation = TInterpolation.LINEAR # ------------------------- Constructors ---------------------------------- def __init__(self, _inner) -> None: super().__init__() @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: + def from_hexwkb(cls: type[Self], hexwkb: str, srid: int | None = None) -> Self: result = super().from_hexwkb(hexwkb) return result.set_srid(srid) if srid is not None else result @@ -71,9 +66,9 @@ def __str__(self): A new :class:`str` representing the temporal point. MEOS Functions: - tpoint_out + tspatial_as_text """ - return tpoint_as_text(self._inner, 15) + return tspatial_as_text(self._inner, 15) def as_wkt(self, precision: int = 15) -> str: """ @@ -86,9 +81,9 @@ def as_wkt(self, precision: int = 15) -> str: A new :class:`str` representing the temporal point. MEOS Functions: - tpoint_out + tspatial_as_text """ - return tpoint_as_text(self._inner, precision) + return tspatial_as_text(self._inner, precision) def as_ewkt(self, precision: int = 15) -> str: """ @@ -101,17 +96,22 @@ def as_ewkt(self, precision: int = 15) -> str: A new :class:`str` representing the temporal point . MEOS Functions: - tpoint_as_ewkt + tspatial_as_ewkt """ - return tpoint_as_ewkt(self._inner, precision) + return tspatial_as_ewkt(self._inner, precision) def as_geojson( - self, option: int = 1, precision: int = 15, srs: Optional[str] = None + self, + unary_union: bool = False, + option: int = 1, + precision: int = 15, + srs: str | None = None, ) -> str: """ Returns the trajectory of the temporal point as a GeoJSON string. Args: + unary_union: If `True`, resulting geometry will be simplified applying a unary union (ST_UnaryUnion) option: The option to use when serializing the trajectory. precision: The precision of the returned geometry. srs: The spatial reference system of the returned geometry. @@ -120,27 +120,26 @@ def as_geojson( A new GeoJSON string representing the trajectory of the temporal point. MEOS Functions: - gserialized_as_geojson + geo_as_geojson """ - return geo_as_geojson(tpoint_trajectory(self._inner), option, precision, srs) + return geo_as_geojson(tpoint_trajectory(self._inner, unary_union), option, precision, srs) - def to_shapely_geometry(self, precision: int = 15) -> shpb.BaseGeometry: + def to_shapely_geometry(self, precision: int = 15, unary_union: bool = False) -> shpb.BaseGeometry: """ Returns the trajectory of the temporal point as a Shapely geometry. Args: precision: The precision of the returned geometry. + unary_union: If `True`, resulting geometry will be simplified applying a unary union (ST_UnaryUnion) Returns: A new :class:`~shapely.geometry.base.BaseGeometry` representing the trajectory. MEOS Functions: - gserialized_to_shapely_geometry + gserialized_to_shapely_geometry, tpoint_trajectory """ - return gserialized_to_shapely_geometry( - tpoint_trajectory(self._inner), precision - ) + return gserialized_to_shapely_geometry(tpoint_trajectory(self._inner, unary_union), precision) # ------------------------- Accessors ------------------------------------- def bounding_box(self) -> STBox: @@ -151,13 +150,13 @@ def bounding_box(self) -> STBox: An :class:`~pymeos.boxes.STBox` representing the bounding box. MEOS Functions: - tpoint_to_stbox + tspatial_to_stbox """ from ..boxes import STBox - return STBox(_inner=tpoint_to_stbox(self._inner)) + return STBox(_inner=tspatial_to_stbox(self._inner)) - def values(self, precision: int = 15) -> List[shp.Point]: + def values(self, precision: int = 15) -> list[shp.Point]: """ Returns the values of the temporal point. @@ -177,9 +176,9 @@ def start_value(self, precision: int = 15) -> shp.Point: A :class:`~shapely.geometry.Point` with the start value. MEOS Functions: - tpoint_start_value + tgeo_start_value """ - return gserialized_to_shapely_point(tpoint_start_value(self._inner), precision) + return gserialized_to_shapely_point(tgeo_start_value(self._inner), precision) def end_value(self, precision: int = 15) -> shp.Point: """ @@ -189,11 +188,11 @@ def end_value(self, precision: int = 15) -> shp.Point: A :class:`~shapely.geometry.Point` with the end value. MEOS Functions: - tpoint_end_value + tgeo_end_value """ - return gserialized_to_shapely_point(tpoint_end_value(self._inner), precision) + return gserialized_to_shapely_point(tgeo_end_value(self._inner), precision) - def value_set(self, precision: int = 15) -> Set[shp.Point]: + def value_set(self, precision: int = 15) -> set[shp.Point]: """ Returns the set of values of `self`. Note that when the interpolation is linear, the set will contain only the waypoints. @@ -202,12 +201,10 @@ def value_set(self, precision: int = 15) -> Set[shp.Point]: A :class:`set` of :class:`~shapely.geometry.Point` with the values. MEOS Functions: - tpoint_values + tgeo_values """ - values, count = tpoint_values(self._inner) - return { - gserialized_to_shapely_point(values[i], precision) for i in range(count) - } + values, count = tgeo_values(self._inner) + return {gserialized_to_shapely_point(values[i], precision) for i in range(count)} def value_at_timestamp(self, timestamp: datetime, precision: int = 15) -> shp.Point: """ @@ -221,12 +218,10 @@ def value_at_timestamp(self, timestamp: datetime, precision: int = 15) -> shp.Po A :class:`~shapely.geometry.Point` with the value. MEOS Functions: - tpoint_value_at_timestamp + tgeo_value_at_timestamp """ return gserialized_to_shapely_point( - tpoint_value_at_timestamptz( - self._inner, datetime_to_timestamptz(timestamp), True - )[0], + tgeo_value_at_timestamptz(self._inner, datetime_to_timestamptz(timestamp), True)[0], precision, ) @@ -319,7 +314,7 @@ def has_z(self) -> bool: """ return self.bounding_box().has_z() - def stboxes(self) -> List[STBox]: + def stboxes(self) -> list[STBox]: """ Returns a collection of :class:`STBox`es representing the bounding boxes of the segments of the temporal point. @@ -331,7 +326,7 @@ def stboxes(self) -> List[STBox]: """ from ..boxes import STBox - result, count = tpoint_stboxes(self._inner) + result, count = tgeo_stboxes(self._inner) return [STBox(_inner=result + i) for i in range(count)] def is_simple(self) -> bool: @@ -346,7 +341,7 @@ def is_simple(self) -> bool: """ return tpoint_is_simple(self._inner) - def bearing(self, other: Union[shpb.BaseGeometry, TPoint]) -> TFloat: + def bearing(self, other: shpb.BaseGeometry | TPoint) -> TFloat: """ Returns the temporal bearing between the temporal point and `other`. @@ -432,7 +427,7 @@ def srid(self) -> int: MEOS Functions: tpoint_srid """ - return tpoint_srid(self._inner) + return tspatial_srid(self._inner) def set_srid(self: Self, srid: int) -> Self: """ @@ -440,7 +435,7 @@ def set_srid(self: Self, srid: int) -> Self: """ - return self.__class__(_inner=tpoint_set_srid(self._inner, srid)) + return self.__class__(_inner=tspatial_set_srid(self._inner, srid)) # ------------------------- Transformations ------------------------------- def round(self, max_decimals: int = 0) -> TPoint: @@ -453,10 +448,10 @@ def round(self, max_decimals: int = 0) -> TPoint: MEOS Functions: tpoint_round """ - result = tpoint_round(self._inner, max_decimals) + result = temporal_round(self._inner, max_decimals) return Temporal._factory(result) - def make_simple(self) -> List[TPoint]: + def make_simple(self) -> list[TPoint]: """ Split the temporal point into a collection of simple temporal points. @@ -469,26 +464,6 @@ def make_simple(self) -> List[TPoint]: result, count = tpoint_make_simple(self._inner) return [Temporal._factory(result[i]) for i in range(count)] - def expand(self, other: Union[int, float]) -> STBox: - """ - Expands ``self`` with `other`. - The result is equal to ``self`` but with the spatial dimensions - expanded by `other` in all directions. - - Args: - other: The object to expand ``self`` with. - - Returns: - A new :class:`STBox` instance. - - MEOS Functions: - tpoint_expand_space - """ - from ..boxes import STBox - - result = tpoint_expand_space(self._inner, float(other)) - return STBox(_inner=result) - def transform(self: Self, srid: int) -> Self: """ Returns a new :class:`TPoint` of the same subclass of ``self`` transformed to another SRID @@ -500,16 +475,13 @@ def transform(self: Self, srid: int) -> Self: A new :class:`TPoint` instance MEOS Functions: - tpoint_transform + tspatial_transform """ - srids = (self.srid(), srid) - if srids not in self._projection_cache: - self._projection_cache[srids] = lwproj_transform(*srids) - result = tpoint_transform_pj(self._inner, srid, self._projection_cache[srids]) + result = tspatial_transform(self._inner, srid) return Temporal._factory(result) # ------------------------- Restrictions ---------------------------------- - def at(self, other: Union[shpb.BaseGeometry, GeoSet, STBox, Time]) -> TG: + def at(self, other: shpb.BaseGeometry | GeoSet | STBox | Time) -> TG: """ Returns a new temporal object with the values of `self` restricted to `other`. @@ -530,16 +502,16 @@ def at(self, other: Union[shpb.BaseGeometry, GeoSet, STBox, Time]) -> TG: result = tpoint_at_value(self._inner, gs) elif isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tpoint_at_geom_time(self._inner, gs, None, None) + result = tgeo_at_geom(self._inner, gs) elif isinstance(other, GeoSet): result = temporal_at_values(self._inner, other._inner) elif isinstance(other, STBox): - result = tpoint_at_stbox(self._inner, other._inner, True) + result = tgeo_at_stbox(self._inner, other._inner, True) else: return super().at(other) return Temporal._factory(result) - def minus(self, other: Union[shpb.BaseGeometry, GeoSet, STBox, Time]) -> TG: + def minus(self, other: shpb.BaseGeometry | GeoSet | STBox | Time) -> TG: """ Returns a new temporal object with the values of `self` restricted to the complement of `other`. @@ -560,17 +532,17 @@ def minus(self, other: Union[shpb.BaseGeometry, GeoSet, STBox, Time]) -> TG: result = tpoint_minus_value(self._inner, gs) elif isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tpoint_minus_geom_time(self._inner, gs, None, None) + result = tgeo_minus_geom(self._inner, gs) elif isinstance(other, GeoSet): result = temporal_minus_values(self._inner, other._inner) elif isinstance(other, STBox): - result = tpoint_minus_stbox(self._inner, other._inner, True) + result = tgeo_minus_stbox(self._inner, other._inner, True) else: return super().minus(other) return Temporal._factory(result) # ------------------------- Position Operations --------------------------- - def is_left(self, other: Union[Temporal, Box]) -> bool: + def is_left(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is left to the bounding box of `other`. @@ -585,7 +557,7 @@ def is_left(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_left(other) - def is_over_or_left(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_left(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or left to the bounding box of `other`. @@ -600,7 +572,7 @@ def is_over_or_left(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_over_or_left(other) - def is_right(self, other: Union[Temporal, Box]) -> bool: + def is_right(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is right to the bounding box of `other`. @@ -615,7 +587,7 @@ def is_right(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_right(other) - def is_over_or_right(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_right(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or right to the bounding box of `other`. @@ -630,7 +602,7 @@ def is_over_or_right(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_over_or_right(other) - def is_below(self, other: Union[Temporal, Box]) -> bool: + def is_below(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is below to the bounding box of `other`. @@ -645,7 +617,7 @@ def is_below(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_below(other) - def is_over_or_below(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_below(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or below to the bounding box of `other`. @@ -660,7 +632,7 @@ def is_over_or_below(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_over_or_below(other) - def is_above(self, other: Union[Temporal, Box]) -> bool: + def is_above(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is above to the bounding box of `other`. @@ -675,7 +647,7 @@ def is_above(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_above(other) - def is_over_or_above(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_above(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or above to the bounding box of `other`. @@ -690,7 +662,7 @@ def is_over_or_above(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_over_or_above(other) - def is_front(self, other: Union[Temporal, Box]) -> bool: + def is_front(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is front to the bounding box of `other`. @@ -705,7 +677,7 @@ def is_front(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_front(other) - def is_over_or_front(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_front(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or front to the bounding box of `other`. @@ -720,7 +692,7 @@ def is_over_or_front(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_over_or_front(other) - def is_behind(self, other: Union[Temporal, Box]) -> bool: + def is_behind(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is behind to the bounding box of `other`. @@ -735,7 +707,7 @@ def is_behind(self, other: Union[Temporal, Box]) -> bool: """ return self.bounding_box().is_behind(other) - def is_over_or_behind(self, other: Union[Temporal, Box]) -> bool: + def is_over_or_behind(self, other: Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is over or behind to the bounding box of `other`. @@ -751,7 +723,7 @@ def is_over_or_behind(self, other: Union[Temporal, Box]) -> bool: return self.bounding_box().is_over_or_behind(other) # ------------------------- Ever Spatial Relationships -------------------- - def is_ever_contained_in(self, container: Union[shpb.BaseGeometry, STBox]) -> bool: + def is_ever_contained_in(self, container: shpb.BaseGeometry | STBox) -> bool: """ Returns whether the temporal point is ever contained by `container`. @@ -762,20 +734,20 @@ def is_ever_contained_in(self, container: Union[shpb.BaseGeometry, STBox]) -> bo A :class:`bool` indicating whether the temporal point is ever contained by `container`. MEOS Functions: - econtains_geo_tpoint + econtains_geo_tgeo """ from ..boxes import STBox if isinstance(container, shpb.BaseGeometry): gs = geo_to_gserialized(container, isinstance(self, TGeogPoint)) - result = econtains_geo_tpoint(gs, self._inner) + result = econtains_geo_tgeo(gs, self._inner) elif isinstance(container, STBox): - result = econtains_geo_tpoint(stbox_to_geo(container._inner), self._inner) + result = econtains_geo_tgeo(stbox_to_geo(container._inner), self._inner) else: raise TypeError(f"Operation not supported with type {container.__class__}") return result == 1 - def is_ever_disjoint(self, other: TPoint) -> bool: + def is_ever_disjoint(self, other: shpb.BaseGeometry | TPoint) -> bool: """ Returns whether the temporal point is ever disjoint from `other`. @@ -786,17 +758,18 @@ def is_ever_disjoint(self, other: TPoint) -> bool: A :class:`bool` indicating whether the temporal point is ever disjoint from `other`. MEOS Functions: - edisjoint_tpoint_geo, edisjoint_tpoint_tpoint + edisjoint_tgeo_geo, edisjoint_tgeo_tgeo """ - if isinstance(other, TPoint): - result = edisjoint_tpoint_tpoint(self._inner, other._inner) + if isinstance(other, shpb.BaseGeometry): + gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) + result = edisjoint_tgeo_geo(self._inner, gs) + elif isinstance(other, TPoint): + result = edisjoint_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return result == 1 - def is_ever_within_distance( - self, other: Union[shpb.BaseGeometry, TPoint, STBox], distance: float - ) -> bool: + def is_ever_within_distance(self, other: shpb.BaseGeometry | TPoint | STBox, distance: float) -> bool: """ Returns whether the temporal point is ever within `distance` of `other`. @@ -808,24 +781,22 @@ def is_ever_within_distance( A :class:`bool` indicating whether the temporal point is ever within `distance` of `other`. MEOS Functions: - edwithin_tpoint_geo, edwithin_tpoint_tpoint + edwithin_tgeo_geo, edwithin_tgeo_tgeo """ from ..boxes import STBox if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = edwithin_tpoint_geo(self._inner, gs, distance) + result = edwithin_tgeo_geo(self._inner, gs, distance) elif isinstance(other, STBox): - result = edwithin_tpoint_geo( - self._inner, stbox_to_geo(other._inner), distance - ) + result = edwithin_tgeo_geo(self._inner, stbox_to_geo(other._inner), distance) elif isinstance(other, TPoint): - result = edwithin_tpoint_tpoint(self._inner, other._inner, distance) + result = edwithin_tgeo_tgeo(self._inner, other._inner, distance) else: raise TypeError(f"Operation not supported with type {other.__class__}") return result == 1 - def ever_intersects(self, other: Union[shpb.BaseGeometry, TPoint, STBox]) -> bool: + def ever_intersects(self, other: shpb.BaseGeometry | TPoint | STBox) -> bool: """ Returns whether the temporal point ever intersects `other`. @@ -836,22 +807,22 @@ def ever_intersects(self, other: Union[shpb.BaseGeometry, TPoint, STBox]) -> boo A :class:`bool` indicating whether the temporal point ever intersects `other`. MEOS Functions: - eintersects_tpoint_geo, eintersects_tpoint_tpoint + eintersects_tgeo_geo, eintersects_tgeo_tgeo """ from ..boxes import STBox if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = eintersects_tpoint_geo(self._inner, gs) + result = eintersects_tgeo_geo(self._inner, gs) elif isinstance(other, STBox): - result = eintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + result = eintersects_tgeo_geo(self._inner, stbox_to_geo(other._inner)) elif isinstance(other, TPoint): - result = eintersects_tpoint_tpoint(self._inner, other._inner) + result = eintersects_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return result == 1 - def ever_touches(self, other: Union[shpb.BaseGeometry, STBox]) -> bool: + def ever_touches(self, other: shpb.BaseGeometry | STBox | TPoint) -> bool: """ Returns whether the temporal point ever touches `other`. @@ -862,23 +833,23 @@ def ever_touches(self, other: Union[shpb.BaseGeometry, STBox]) -> bool: A :class:`bool` indicating whether the temporal point ever touches `other`. MEOS Functions: - etouches_tpoint_geo + etouches_tgeo_geo, etouches_tgeo_tgeo """ from ..boxes import STBox if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = etouches_tpoint_geo(self._inner, gs) + result = etouches_tgeo_geo(self._inner, gs) elif isinstance(other, STBox): - result = etouches_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + result = etouches_tgeo_geo(self._inner, stbox_to_geo(other._inner)) + elif isinstance(other, TPoint): + result = etouches_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return result == 1 # ------------------------- Temporal Spatial Relationships ---------------- - def is_spatially_contained_in( - self, container: Union[shpb.BaseGeometry, STBox] - ) -> TBool: + def is_spatially_contained_in(self, container: shpb.BaseGeometry | STBox) -> TBool: """ Returns a new temporal boolean indicating whether the temporal point is contained by `container`. @@ -895,127 +866,16 @@ def is_spatially_contained_in( if isinstance(container, shpb.BaseGeometry): gs = geo_to_gserialized(container, isinstance(self, TGeogPoint)) - result = tcontains_geo_tpoint(gs, self._inner, False, False) + result = tcontains_geo_tgeo(gs, self._inner, False, False) elif isinstance(container, STBox): gs = stbox_to_geo(container._inner) - result = tcontains_geo_tpoint(gs, self._inner, False, False) + result = tcontains_geo_tgeo(gs, self._inner, False, False) else: raise TypeError(f"Operation not supported with type {container.__class__}") return Temporal._factory(result) - def disjoint(self, other: Union[shpb.BaseGeometry, STBox]) -> TBool: - """ - Returns a new temporal boolean indicating whether the temporal point intersects `other`. - - Args: - other: An object to check for intersection with. - - Returns: - A new :TBool: indicating whether the temporal point intersects `other`. - - MEOS Functions: - tintersects_tpoint_geo - """ - from ..boxes import STBox - - if isinstance(other, shpb.BaseGeometry): - gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tdisjoint_tpoint_geo(self._inner, gs, False, False) - elif isinstance(other, STBox): - result = tdisjoint_tpoint_geo( - self._inner, stbox_to_geo(other._inner), False, False - ) - else: - raise TypeError(f"Operation not supported with type {other.__class__}") - return Temporal._factory(result) - - def within_distance( - self, other: Union[shpb.BaseGeometry, TPoint, STBox], distance: float - ) -> TBool: - """ - Returns a new temporal boolean indicating whether the temporal point is within `distance` of `other`. - - Args: - other: An object to check the distance to. - distance: The distance to check in units of the spatial reference system. - - Returns: - A new :TBool: indicating whether the temporal point is within `distance` of `other`. - - MEOS Functions: - tdwithin_tpoint_geo, tdwithin_tpoint_tpoint - """ - from ..boxes import STBox - - if isinstance(other, shpb.BaseGeometry): - gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tdwithin_tpoint_geo(self._inner, gs, distance, False, False) - elif isinstance(other, STBox): - result = tdwithin_tpoint_geo( - self._inner, stbox_to_geo(other._inner), distance, False, False - ) - elif isinstance(other, TPoint): - result = tdwithin_tpoint_tpoint( - self._inner, other._inner, distance, False, False - ) - else: - raise TypeError(f"Operation not supported with type {other.__class__}") - return Temporal._factory(result) - - def intersects(self, other: Union[shpb.BaseGeometry, STBox]) -> TBool: - """ - Returns a new temporal boolean indicating whether the temporal point intersects `other`. - - Args: - other: An object to check for intersection with. - - Returns: - A new :TBool: indicating whether the temporal point intersects `other`. - - MEOS Functions: - tintersects_tpoint_geo - """ - from ..boxes import STBox - - if isinstance(other, shpb.BaseGeometry): - gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tintersects_tpoint_geo(self._inner, gs, False, False) - elif isinstance(other, STBox): - result = tintersects_tpoint_geo( - self._inner, stbox_to_geo(other._inner), False, False - ) - else: - raise TypeError(f"Operation not supported with type {other.__class__}") - return Temporal._factory(result) - - def touches(self, other: Union[shpb.BaseGeometry, STBox]) -> TBool: - """ - Returns a new temporal boolean indicating whether the temporal point touches `other`. - - Args: - other: An object to check for touching with. - - Returns: - A new :TBool: indicating whether the temporal point touches `other`. - - MEOS Functions: - ttouches_tpoint_geo - """ - from ..boxes import STBox - - if isinstance(other, shpb.BaseGeometry): - gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = ttouches_tpoint_geo(self._inner, gs, False, False) - elif isinstance(other, STBox): - result = ttouches_tpoint_geo( - self._inner, stbox_to_geo(other._inner), False, False - ) - else: - raise TypeError(f"Operation not supported with type {other.__class__}") - return Temporal._factory(result) - # ------------------------- Distance Operations --------------------------- - def distance(self, other: Union[shpb.BaseGeometry, TPoint, STBox]) -> TFloat: + def distance(self, other: shpb.BaseGeometry | TPoint | STBox) -> TFloat: """ Returns the temporal distance between the temporal point and `other`. @@ -1026,24 +886,22 @@ def distance(self, other: Union[shpb.BaseGeometry, TPoint, STBox]) -> TFloat: A new :class:`TFloat` indicating the temporal distance between the temporal point and `other`. MEOS Functions: - distance_tpoint_point, distance_tpoint_tpoint + tdistance_tgeo_geo, tdistance_tgeo_tgeo """ from ..boxes import STBox if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = distance_tpoint_point(self._inner, gs) + result = tdistance_tgeo_geo(self._inner, gs) elif isinstance(other, STBox): - result = distance_tpoint_point(self._inner, stbox_to_geo(other._inner)) + result = tdistance_tgeo_geo(self._inner, stbox_to_geo(other._inner)) elif isinstance(other, TPoint): - result = distance_tpoint_tpoint(self._inner, other._inner) + result = tdistance_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def nearest_approach_distance( - self, other: Union[shpb.BaseGeometry, STBox, TPoint] - ) -> float: + def nearest_approach_distance(self, other: shpb.BaseGeometry | STBox | TPoint) -> float: """ Returns the nearest approach distance between the temporal point and `other`. @@ -1054,21 +912,21 @@ def nearest_approach_distance( A :class:`float` indicating the nearest approach distance between the temporal point and `other`. MEOS Functions: - nad_tpoint_geo, nad_tpoint_stbox, nad_tpoint_tpoint + nad_tgeo_geo, nad_tgeo_stbox, nad_tgeo_tgeo """ from ..boxes import STBox if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - return nad_tpoint_geo(self._inner, gs) + return nad_tgeo_geo(self._inner, gs) elif isinstance(other, STBox): - return nad_tpoint_stbox(self._inner, other._inner) + return nad_tgeo_stbox(self._inner, other._inner) elif isinstance(other, TPoint): - return nad_tpoint_tpoint(self._inner, other._inner) + return nad_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") - def nearest_approach_instant(self, other: Union[shpb.BaseGeometry, TPoint]) -> TI: + def nearest_approach_instant(self, other: shpb.BaseGeometry | TPoint) -> TI: """ Returns the nearest approach instant between the temporal point and `other`. @@ -1079,20 +937,18 @@ def nearest_approach_instant(self, other: Union[shpb.BaseGeometry, TPoint]) -> T A new temporal instant indicating the nearest approach instant between the temporal point and `other`. MEOS Functions: - nai_tpoint_geo, nai_tpoint_tpoint + nai_tgeo_geo, nai_tgeo_tgeo """ if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = nai_tpoint_geo(self._inner, gs) + result = nai_tgeo_geo(self._inner, gs) elif isinstance(other, TPoint): - result = nai_tpoint_tpoint(self._inner, other._inner) + result = nai_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(result) - def shortest_line( - self, other: Union[shpb.BaseGeometry, TPoint] - ) -> shpb.BaseGeometry: + def shortest_line(self, other: shpb.BaseGeometry | TPoint) -> shpb.BaseGeometry: """ Returns the shortest line between the temporal point and `other`. @@ -1104,13 +960,13 @@ def shortest_line( and `other`. MEOS Functions: - shortestline_tpoint_geo, shortestline_tpoint_tpoint + shortestline_tgeo_geo, shortestline_tgeo_tgeo """ if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = shortestline_tpoint_geo(self._inner, gs) + result = shortestline_tgeo_geo(self._inner, gs) elif isinstance(other, TPoint): - result = shortestline_tpoint_tpoint(self._inner, other._inner) + result = shortestline_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return gserialized_to_shapely_geometry(result, 10) @@ -1119,11 +975,11 @@ def shortest_line( def tile( self, size: float, - duration: Optional[Union[timedelta, str]] = None, - origin: Optional[shpb.BaseGeometry] = None, - start: Union[datetime, str, None] = None, - remove_empty: Optional[bool] = False, - ) -> List[TG]: + duration: timedelta | str | None = None, + origin: shpb.BaseGeometry | None = None, + start: datetime | str | None = None, + remove_empty: bool | None = False, + ) -> list[TG]: """ Split the temporal point into segments following the tiling of the bounding box. @@ -1160,12 +1016,12 @@ def tile( def space_split( self, xsize: float, - ysize: Optional[float] = None, - zsize: Optional[float] = None, - origin: Optional[shpb.BaseGeometry] = None, + ysize: float | None = None, + zsize: float | None = None, + origin: shpb.BaseGeometry | None = None, bitmatrix: bool = False, include_border: bool = True, - ) -> List[Temporal]: + ) -> list[Temporal]: """ Splits `self` into fragments with respect to space buckets @@ -1189,15 +1045,9 @@ def space_split( gs = ( geo_to_gserialized(origin, isinstance(self, TGeogPoint)) if origin is not None - else ( - pgis_geography_in("Point(0 0 0)", -1) - if isinstance(self, TGeogPoint) - else pgis_geometry_in("Point(0 0 0)", -1) - ) - ) - fragments, values, count = tpoint_space_split( - self._inner, xsize, ysz, zsz, gs, bitmatrix, include_border + else (geog_in("Point(0 0 0)", -1) if isinstance(self, TGeogPoint) else geom_in("Point(0 0 0)", -1)) ) + fragments, values, count = tgeo_space_split(self._inner, xsize, ysz, zsz, gs, bitmatrix, include_border) from ..factory import _TemporalFactory return [_TemporalFactory.create_temporal(fragments[i]) for i in range(count)] @@ -1205,14 +1055,14 @@ def space_split( def space_time_split( self, xsize: float, - duration: Union[str, timedelta], - ysize: Optional[float] = None, - zsize: Optional[float] = None, - origin: Optional[shpb.BaseGeometry] = None, - time_start: Optional[Union[str, datetime]] = None, + duration: str | timedelta, + ysize: float | None = None, + zsize: float | None = None, + origin: shpb.BaseGeometry | None = None, + time_start: str | datetime | None = None, bitmatrix: bool = False, include_border: bool = True, - ) -> List[Temporal]: + ) -> list[Temporal]: """ Splits `self` into fragments with respect to space and tstzspan buckets. @@ -1236,19 +1086,11 @@ def space_time_split( """ ysz = ysize if ysize is not None else xsize zsz = zsize if zsize is not None else xsize - dt = ( - timedelta_to_interval(duration) - if isinstance(duration, timedelta) - else pg_interval_in(duration, -1) - ) + dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) else pg_interval_in(duration, -1) gs = ( geo_to_gserialized(origin, isinstance(self, TGeogPoint)) if origin is not None - else ( - pgis_geography_in("Point(0 0 0)", -1) - if isinstance(self, TGeogPoint) - else pgis_geometry_in("Point(0 0 0)", -1) - ) + else (geog_in("Point(0 0 0)", -1) if isinstance(self, TGeogPoint) else geom_in("Point(0 0 0)", -1)) ) if time_start is None: st = pg_timestamptz_in("2000-01-03", -1) @@ -1258,15 +1100,13 @@ def space_time_split( if isinstance(time_start, datetime) else pg_timestamptz_in(time_start, -1) ) - fragments, points, times, count = tpoint_space_time_split( + fragments, points, times, count = tgeo_space_time_split( self._inner, xsize, ysz, zsz, dt, gs, st, bitmatrix, include_border ) return [Temporal._factory(fragments[i]) for i in range(count)] -class TPointInst( - TInstant[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC -): +class TPointInst(TInstant[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC): """ Abstract class for temporal point instants. """ @@ -1293,9 +1133,7 @@ def z(self) -> TFloatInst: return super().z() -class TPointSeq( - TSequence[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC -): +class TPointSeq(TSequence[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC): """ Abstract class for temporal point sequences. """ @@ -1328,9 +1166,7 @@ def plot(self, *args, **kwargs): return TemporalPointSequencePlotter.plot_xy(self, *args, **kwargs) -class TPointSeqSet( - TSequenceSet[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC -): +class TPointSeqSet(TSequenceSet[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC): """ Abstract class for temporal point sequence sets. """ @@ -1349,19 +1185,11 @@ def to_dataframe(self, precision: int = 15) -> GeoDataFrame: gpd = import_geopandas() sequences = self.sequences() data = { - "sequence": [ - i + 1 - for i, seq in enumerate(sequences) - for _ in range(seq.num_instants()) - ], + "sequence": [i + 1 for i, seq in enumerate(sequences) for _ in range(seq.num_instants())], "time": [t for seq in sequences for t in seq.timestamps()], - "geometry": [ - v for seq in sequences for v in seq.values(precision=precision) - ], + "geometry": [v for seq in sequences for v in seq.values(precision=precision)], } - return gpd.GeoDataFrame(data, crs=self.srid()).set_index( - keys=["sequence", "time"] - ) + return gpd.GeoDataFrame(data, crs=self.srid()).set_index(keys=["sequence", "time"]) def x(self) -> TFloatSeqSet: return super().x() @@ -1391,9 +1219,7 @@ def plot(self, *args, **kwargs): return TemporalPointSequenceSetPlotter.plot_xy(self, *args, **kwargs) -class TGeomPoint( - TPoint["TGeomPoint", "TGeomPointInst", "TGeomPointSeq", "TGeomPointSeqSet"], ABC -): +class TGeomPoint(TPoint["TGeomPoint", "TGeomPointInst", "TGeomPointSeq", "TGeomPointSeqSet"], ABC): """ Abstract class for temporal geometric points. """ @@ -1426,15 +1252,11 @@ def from_base_temporal(value: shpb.BaseGeometry, base: Temporal) -> TGeomPoint: @staticmethod @overload - def from_base_time( - value: shpb.BaseGeometry, base: datetime, interpolation: None = None - ) -> TGeomPointInst: ... + def from_base_time(value: shpb.BaseGeometry, base: datetime, interpolation: None = None) -> TGeomPointInst: ... @staticmethod @overload - def from_base_time( - value: shpb.BaseGeometry, base: TsTzSet, interpolation: None = None - ) -> TGeomPointSeq: ... + def from_base_time(value: shpb.BaseGeometry, base: TsTzSet, interpolation: None = None) -> TGeomPointSeq: ... @staticmethod @overload @@ -1451,9 +1273,7 @@ def from_base_time( ) -> TGeomPointSeqSet: ... @staticmethod - def from_base_time( - value: shpb.BaseGeometry, base: Time, interpolation: TInterpolation = None - ) -> TGeomPoint: + def from_base_time(value: shpb.BaseGeometry, base: Time, interpolation: TInterpolation = None) -> TGeomPoint: """ Creates a temporal geometric point from a base geometry and a time value. @@ -1471,25 +1291,17 @@ def from_base_time( """ gs = geometry_to_gserialized(value) if isinstance(base, datetime): - return TGeomPointInst( - _inner=tpointinst_make(gs, datetime_to_timestamptz(base)) - ) + return TGeomPointInst(_inner=tpointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TsTzSet): return TGeomPointSeq(_inner=tpointseq_from_base_tstzset(gs, base._inner)) elif isinstance(base, TsTzSpan): - return TGeomPointSeq( - _inner=tpointseq_from_base_tstzspan(gs, base._inner, interpolation) - ) + return TGeomPointSeq(_inner=tpointseq_from_base_tstzspan(gs, base._inner, interpolation)) elif isinstance(base, TsTzSpanSet): - return TGeomPointSeqSet( - _inner=tpointseqset_from_base_tstzspanset( - gs, base._inner, interpolation - ) - ) + return TGeomPointSeqSet(_inner=tpointseqset_from_base_tstzspanset(gs, base._inner, interpolation)) raise TypeError(f"Operation not supported with type {base.__class__}") @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -1515,9 +1327,9 @@ def to_geographic(self) -> TGeogPoint: A new :class:`TGeogPoint` object. MEOS Functions: - tgeompoint_to_tgeogpoint + tgeometry_to_tgeography """ - result = tgeompoint_to_tgeogpoint(self._inner) + result = tgeometry_to_tgeography(self._inner) return Temporal._factory(result) def to_dataframe(self) -> GeoDataFrame: @@ -1534,8 +1346,115 @@ def to_dataframe(self) -> GeoDataFrame: } return gpd.GeoDataFrame(data, crs=self.srid()).set_index(keys=["time"]) + # --------------------- Temporal Spatial Relationships -------------------- + + def disjoint(self, other: shpb.BaseGeometry | STBox | TPoint) -> TBool: + """ + Returns a new temporal boolean indicating whether the temporal point intersects `other`. + + Args: + other: An object to check for intersection with. + + Returns: + A new :TBool: indicating whether the temporal point intersects `other`. + + MEOS Functions: + tdisjoint_tgeo_geo, tdisjoint_tgeo_tgeo + """ + from ..boxes import STBox + + if isinstance(other, shpb.BaseGeometry): + gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) + result = tdisjoint_tgeo_geo(self._inner, gs, False, False) + elif isinstance(other, STBox): + result = tdisjoint_tgeo_geo(self._inner, stbox_to_geo(other._inner), False, False) + elif isinstance(other, TPoint): + result = tdisjoint_tgeo_tgeo(self._inner, other._inner, False, False) + else: + raise TypeError(f"Operation not supported with type {other.__class__}") + return Temporal._factory(result) + + def intersects(self, other: shpb.BaseGeometry | STBox | TPoint) -> TBool: + """ + Returns a new temporal boolean indicating whether the temporal point intersects `other`. + + Args: + other: An object to check for intersection with. + + Returns: + A new :TBool: indicating whether the temporal point intersects `other`. + + MEOS Functions: + tintersects_tgeo_geo, tintersects_tgeo_tgeo + """ + from ..boxes import STBox + + if isinstance(other, shpb.BaseGeometry): + gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) + result = tintersects_tgeo_geo(self._inner, gs, False, False) + elif isinstance(other, STBox): + result = tintersects_tgeo_geo(self._inner, stbox_to_geo(other._inner), False, False) + elif isinstance(other, TPoint): + result = tintersects_tgeo_tgeo(self._inner, other._inner, False, False) + else: + raise TypeError(f"Operation not supported with type {other.__class__}") + return Temporal._factory(result) + + def touches(self, other: shpb.BaseGeometry | STBox | TGeomPoint) -> TBool: + """ + Returns a new temporal boolean indicating whether the temporal point touches `other`. + + Args: + other: An object to check for touching with. + + Returns: + A new :TBool: indicating whether the temporal point touches `other`. + + MEOS Functions: + ttouches_tgeo_geo, ttouches_tgeo_tgeo + """ + from ..boxes import STBox + + if isinstance(other, shpb.BaseGeometry): + gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) + result = ttouches_tgeo_geo(self._inner, gs, False, False) + elif isinstance(other, STBox): + result = ttouches_tgeo_geo(self._inner, stbox_to_geo(other._inner), False, False) + elif isinstance(other, TGeomPoint): + result = ttouches_tgeo_tgeo(self._inner, other._inner, False, False) + else: + raise TypeError(f"Operation not supported with type {other.__class__}") + return Temporal._factory(result) + + def within_distance(self, other: shpb.BaseGeometry | TGeomPoint | STBox, distance: float) -> TBool: + """ + Returns a new temporal boolean indicating whether the temporal point is within `distance` of `other`. + + Args: + other: An object to check the distance to. + distance: The distance to check in units of the spatial reference system. + + Returns: + A new :TBool: indicating whether the temporal point is within `distance` of `other`. + + MEOS Functions: + tdwithin_tgeo_geo, tdwithin_tgeo_tgeo + """ + from ..boxes import STBox + + if isinstance(other, shpb.BaseGeometry): + gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) + result = tdwithin_tgeo_geo(self._inner, gs, distance, False, False) + elif isinstance(other, STBox): + result = tdwithin_tgeo_geo(self._inner, stbox_to_geo(other._inner), distance, False, False) + elif isinstance(other, TGeomPoint): + result = tdwithin_tgeo_tgeo(self._inner, other._inner, distance, False, False) + else: + raise TypeError(f"Operation not supported with type {other.__class__}") + return Temporal._factory(result) + # ------------------------- Ever and Always Comparisons ------------------- - def always_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: + def always_equal(self, value: shpb.BaseGeometry | TGeomPoint) -> bool: """ Returns whether `self` is always equal to `value`. @@ -1546,17 +1465,17 @@ def always_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: True if `self` is always equal to `value`, False otherwise. MEOS Functions: - always_eq_tpoint_point, always_eq_temporal_temporal + always_eq_tgeo_geo, always_eq_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geometry_to_gserialized(value) - return always_eq_tpoint_point(self._inner, gs) > 0 + return always_eq_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeomPoint): - return always_eq_temporal_temporal(self._inner, value._inner) > 0 + return always_eq_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_not_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: + def always_not_equal(self, value: shpb.BaseGeometry | TGeomPoint) -> bool: """ Returns whether `self` is always different to `value`. @@ -1567,17 +1486,17 @@ def always_not_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: True if `self` is always different to `value`, False otherwise. MEOS Functions: - always_ne_tpoint_point, always_ne_temporal_temporal + always_ne_tgeo_geo, always_ne_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geometry_to_gserialized(value) - return always_ne_tpoint_point(self._inner, gs) > 0 + return always_ne_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeomPoint): - return always_ne_temporal_temporal(self._inner, value._inner) > 0 + return always_ne_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: + def ever_equal(self, value: shpb.BaseGeometry | TGeomPoint) -> bool: """ Returns whether `self` is ever equal to `value`. @@ -1588,17 +1507,17 @@ def ever_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: True if `self` is ever equal to `value`, False otherwise. MEOS Functions: - ever_eq_tpoint_point, ever_eq_temporal_temporal + ever_eq_tgeo_geo, ever_eq_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geometry_to_gserialized(value) - return ever_eq_tpoint_point(self._inner, gs) > 0 + return ever_eq_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeomPoint): - return ever_eq_temporal_temporal(self._inner, value._inner) > 0 + return ever_eq_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_not_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: + def ever_not_equal(self, value: shpb.BaseGeometry | TGeomPoint) -> bool: """ Returns whether `self` is ever different to `value`. @@ -1609,17 +1528,17 @@ def ever_not_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: True if `self` is ever different to `value`, False otherwise. MEOS Functions: - ever_ne_tpoint_point, ever_ne_temporal_temporal + ever_ne_tgeo_geo, ever_ne_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geometry_to_gserialized(value) - return ever_ne_tpoint_point(self._inner, gs) > 0 + return ever_ne_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeomPoint): - return ever_ne_temporal_temporal(self._inner, value._inner) > 0 + return ever_ne_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def never_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: + def never_equal(self, value: shpb.BaseGeometry | TGeomPoint) -> bool: """ Returns whether `self` is never equal to `value`. @@ -1630,11 +1549,11 @@ def never_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: True if `self` is never equal to `value`, False otherwise. MEOS Functions: - ever_eq_tpoint_point, ever_eq_temporal_temporal + ever_eq_tgeo_geo, ever_eq_tgeo_tgeo """ return not self.ever_equal(value) - def never_not_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: + def never_not_equal(self, value: shpb.BaseGeometry | TGeomPoint) -> bool: """ Returns whether `self` is never different to `value`. @@ -1645,13 +1564,11 @@ def never_not_equal(self, value: Union[shpb.BaseGeometry, TGeomPoint]) -> bool: True if `self` is never different to `value`, False otherwise. MEOS Functions: - ever_ne_tpoint_point, ever_ne_temporal_temporal + ever_ne_tgeo_geo, ever_ne_tgeo_tgeo """ return not self.ever_not_equal(value) - def is_ever_disjoint( - self, other: Union[shpb.BaseGeometry, TGeomPoint, STBox] - ) -> bool: + def is_ever_disjoint(self, other: shpb.BaseGeometry | TGeomPoint | STBox) -> bool: """ Returns whether the temporal point is ever disjoint from `other`. @@ -1662,23 +1579,23 @@ def is_ever_disjoint( A :class:`bool` indicating whether the temporal point is ever disjoint from `other`. MEOS Functions: - edisjoint_tpoint_geo, edisjoint_tpoint_tpoint + edisjoint_tgeo_geo, edisjoint_tgeo_tgeo """ from ..boxes import STBox if isinstance(other, shpb.BaseGeometry): gs = geo_to_gserialized(other, isinstance(self, TGeogPoint)) - result = edisjoint_tpoint_geo(self._inner, gs) + result = edisjoint_tgeo_geo(self._inner, gs) elif isinstance(other, STBox): - result = edisjoint_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + result = edisjoint_tgeo_geo(self._inner, stbox_to_geo(other._inner)) elif isinstance(other, TGeomPoint): - result = edisjoint_tpoint_tpoint(self._inner, other._inner) + result = edisjoint_tgeo_tgeo(self._inner, other._inner) else: raise TypeError(f"Operation not supported with type {other.__class__}") return result == 1 # ------------------------- Temporal Comparisons -------------------------- - def temporal_equal(self, other: Union[shp.Point, TGeomPoint]) -> TBool: + def temporal_equal(self, other: shp.Point | TGeomPoint) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -1689,16 +1606,16 @@ def temporal_equal(self, other: Union[shp.Point, TGeomPoint]) -> TBool: A :class:`TBool` with the result of the temporal equality relation. MEOS Functions: - teq_tpoint_point, teq_temporal_temporal + teq_tgeo_geo, teq_tgeo_geo """ if isinstance(other, shp.Point): gs = geometry_to_gserialized(other) - result = teq_tpoint_point(self._inner, gs) + result = teq_tgeo_geo(self._inner, gs) else: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[shp.Point, TGeomPoint]) -> TBool: + def temporal_not_equal(self, other: shp.Point | TGeomPoint) -> TBool: """ Returns the temporal inequality relation between `self` and `other`. @@ -1709,11 +1626,11 @@ def temporal_not_equal(self, other: Union[shp.Point, TGeomPoint]) -> TBool: A :class:`TBool` with the result of the temporal inequality relation. MEOS Functions: - tne_tpoint_point, tne_temporal_temporal + tne_tgeo_geo, tne_tgeo_geo """ if isinstance(other, shp.Point): gs = geometry_to_gserialized(other) - result = tne_tpoint_point(self._inner, gs) + result = tne_tgeo_geo(self._inner, gs) else: return super().temporal_not_equal(other) return Temporal._factory(result) @@ -1746,9 +1663,7 @@ def read_from_cursor(value, _=None): raise Exception("ERROR: Could not parse temporal point value") -class TGeogPoint( - TPoint["TGeogPoint", "TGeogPointInst", "TGeogPointSeq", "TGeogPointSeqSet"], ABC -): +class TGeogPoint(TPoint["TGeogPoint", "TGeogPointInst", "TGeogPointSeq", "TGeogPointSeqSet"], ABC): """ Abstract class for representing temporal geographic points. """ @@ -1806,9 +1721,7 @@ def from_base_time( ) -> TGeogPointSeqSet: ... @staticmethod - def from_base_time( - value: shpb.BaseGeometry, base: Time, interpolation: TInterpolation = None - ) -> TGeogPoint: + def from_base_time(value: shpb.BaseGeometry, base: Time, interpolation: TInterpolation = None) -> TGeogPoint: """ Creates a temporal geographic point from a base geometry and a time object. @@ -1826,25 +1739,17 @@ def from_base_time( """ gs = geography_to_gserialized(value) if isinstance(base, datetime): - return TGeogPointInst( - _inner=tpointinst_make(gs, datetime_to_timestamptz(base)) - ) + return TGeogPointInst(_inner=tpointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TsTzSet): return TGeogPointSeq(_inner=tpointseq_from_base_tstzset(gs, base._inner)) elif isinstance(base, TsTzSpan): - return TGeogPointSeq( - _inner=tpointseq_from_base_tstzspan(gs, base._inner, interpolation) - ) + return TGeogPointSeq(_inner=tpointseq_from_base_tstzspan(gs, base._inner, interpolation)) elif isinstance(base, TsTzSpanSet): - return TGeogPointSeqSet( - _inner=tpointseqset_from_base_tstzspanset( - gs, base._inner, interpolation - ) - ) + return TGeogPointSeqSet(_inner=tpointseqset_from_base_tstzspanset(gs, base._inner, interpolation)) raise TypeError(f"Operation not supported with type {base.__class__}") @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -1870,13 +1775,13 @@ def to_geometric(self) -> TGeomPoint: A new :class:`TGeomPoint` object. MEOS Functions: - tgeogpoint_to_tgeompoint + tgeography_to_tgeometry """ - result = tgeogpoint_to_tgeompoint(self._inner) + result = tgeography_to_tgeometry(self._inner) return Temporal._factory(result) # ------------------------- Ever and Always Comparisons ------------------- - def always_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: + def always_equal(self, value: shpb.BaseGeometry | TGeogPoint) -> bool: """ Returns whether `self` is always equal to `value`. @@ -1887,17 +1792,17 @@ def always_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: True if `self` is always equal to `value`, False otherwise. MEOS Functions: - always_eq_tpoint_point, always_eq_temporal_temporal + always_eq_tgeo_geo, always_eq_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geography_to_gserialized(value) - return always_eq_tpoint_point(self._inner, gs) > 0 + return always_eq_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeogPoint): - return always_eq_temporal_temporal(self._inner, value._inner) > 0 + return always_eq_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_not_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: + def always_not_equal(self, value: shpb.BaseGeometry | TGeogPoint) -> bool: """ Returns whether `self` is always different to `value`. @@ -1908,17 +1813,17 @@ def always_not_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: True if `self` is always different to `value`, False otherwise. MEOS Functions: - always_ne_tpoint_point, always_ne_temporal_temporal + always_ne_tgeo_geo, always_ne_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geography_to_gserialized(value) - return always_ne_tpoint_point(self._inner, gs) > 0 + return always_ne_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeogPoint): - return always_ne_temporal_temporal(self._inner, value._inner) > 0 + return always_ne_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: + def ever_equal(self, value: shpb.BaseGeometry | TGeogPoint) -> bool: """ Returns whether `self` is ever equal to `value`. @@ -1929,17 +1834,17 @@ def ever_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: True if `self` is ever equal to `value`, False otherwise. MEOS Functions: - ever_eq_tpoint_point, ever_eq_temporal_temporal + ever_eq_tgeo_geo, ever_eq_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geography_to_gserialized(value) - return ever_eq_tpoint_point(self._inner, gs) > 0 + return ever_eq_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeogPoint): - return ever_eq_temporal_temporal(self._inner, value._inner) > 0 + return ever_eq_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_not_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: + def ever_not_equal(self, value: shpb.BaseGeometry | TGeogPoint) -> bool: """ Returns whether `self` is ever different to `value`. @@ -1950,17 +1855,17 @@ def ever_not_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: True if `self` is ever different to `value`, False otherwise. MEOS Functions: - ever_ne_tpoint_point, ever_ne_temporal_temporal + ever_ne_tgeo_geo, ever_ne_tgeo_tgeo """ if isinstance(value, shpb.BaseGeometry): gs = geography_to_gserialized(value) - return ever_ne_tpoint_point(self._inner, gs) > 0 + return ever_ne_tgeo_geo(self._inner, gs) > 0 elif isinstance(value, TGeogPoint): - return ever_ne_temporal_temporal(self._inner, value._inner) > 0 + return ever_ne_tgeo_tgeo(self._inner, value._inner) > 0 else: raise TypeError(f"Operation not supported with type {value.__class__}") - def never_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: + def never_equal(self, value: shpb.BaseGeometry | TGeogPoint) -> bool: """ Returns whether `self` is never equal to `value`. @@ -1971,11 +1876,11 @@ def never_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: True if `self` is never equal to `value`, False otherwise. MEOS Functions: - ever_eq_tpoint_point, ever_eq_temporal_temporal + ever_eq_tgeo_geo, ever_eq_tgeo_tgeo """ return not self.ever_equal(value) - def never_not_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: + def never_not_equal(self, value: shpb.BaseGeometry | TGeogPoint) -> bool: """ Returns whether `self` is never different to `value`. @@ -1986,12 +1891,12 @@ def never_not_equal(self, value: Union[shpb.BaseGeometry, TGeogPoint]) -> bool: True if `self` is never different to `value`, False otherwise. MEOS Functions: - ever_ne_tpoint_point, ever_ne_temporal_temporal + ever_ne_tgeo_geo, ever_ne_tgeo_tgeo """ return not self.ever_not_equal(value) # ------------------------- Temporal Comparisons -------------------------- - def temporal_equal(self, other: Union[shp.Point, TGeogPoint]) -> TBool: + def temporal_equal(self, other: shp.Point | TGeogPoint) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -2002,16 +1907,16 @@ def temporal_equal(self, other: Union[shp.Point, TGeogPoint]) -> TBool: A :class:`TBool` with the result of the temporal equality relation. MEOS Functions: - teq_tpoint_point, teq_temporal_temporal + teq_tgeo_geo, teq_temporal_temporal """ if isinstance(other, shp.Point): gs = geography_to_gserialized(other) - result = teq_tpoint_point(self._inner, gs) + result = teq_tgeo_geo(self._inner, gs) else: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[shp.Point, TGeogPoint]) -> TBool: + def temporal_not_equal(self, other: shp.Point | TGeogPoint) -> TBool: """ Returns the temporal inequality relation between `self` and `other`. @@ -2022,11 +1927,11 @@ def temporal_not_equal(self, other: Union[shp.Point, TGeogPoint]) -> TBool: A :class:`TBool` with the result of the temporal inequality relation. MEOS Functions: - tne_tpoint_point, tne_temporal_temporal + tne_tgeo_geo, tne_temporal_temporal """ if isinstance(other, shp.Point): gs = geography_to_gserialized(other) - result = tne_tpoint_point(self._inner, gs) + result = tne_tgeo_geo(self._inner, gs) else: return super().temporal_not_equal(other) return Temporal._factory(result) @@ -2072,26 +1977,20 @@ class TGeomPointInst( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - point: Optional[ - Union[str, shp.Point, Tuple[float, float], Tuple[float, float, float]] - ] = None, - timestamp: Optional[Union[str, datetime]] = None, - srid: Optional[int] = 0, + point: str | shp.Point | tuple[float, float] | tuple[float, float, float] | None = None, + timestamp: str | datetime | None = None, + srid: int | None = 0, _inner=None, ) -> None: super().__init__(string=string, value=point, timestamp=timestamp, _inner=_inner) if self._inner is None: if isinstance(point, tuple): - p = f'POINT({" ".join(str(x) for x in point)})' + p = f"POINT({' '.join(str(x) for x in point)})" else: p = f"{point}" - full_str = ( - f"SRID={srid};{p}@{timestamp}" - if srid is not None - else f"{p}@{timestamp}" - ) + full_str = f"SRID={srid};{p}@{timestamp}" if srid is not None else f"{p}@{timestamp}" self._inner = tgeompoint_in(full_str) @@ -2108,26 +2007,20 @@ class TGeogPointInst( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - point: Optional[ - Union[str, shp.Point, Tuple[float, float], Tuple[float, float, float]] - ] = None, - timestamp: Optional[Union[str, datetime]] = None, - srid: Optional[int] = 4326, + point: str | shp.Point | tuple[float, float] | tuple[float, float, float] | None = None, + timestamp: str | datetime | None = None, + srid: int | None = 4326, _inner=None, ) -> None: super().__init__(string=string, value=point, timestamp=timestamp, _inner=_inner) if self._inner is None: if isinstance(point, tuple): - p = f'POINT({" ".join(str(x) for x in point)})' + p = f"POINT({' '.join(str(x) for x in point)})" else: p = f"{point}" - full_str = ( - f"SRID={srid};{p}@{timestamp}" - if srid is not None - else f"{p}@{timestamp}" - ) + full_str = f"SRID={srid};{p}@{timestamp}" if srid is not None else f"{p}@{timestamp}" self._inner = tgeogpoint_in(full_str) @@ -2143,9 +2036,9 @@ class TGeomPointSeq( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, TGeomPointInst]]] = None, + instant_list: list[str | TGeomPointInst] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.LINEAR, @@ -2175,9 +2068,9 @@ class TGeogPointSeq( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, TGeogPointInst]]] = None, + instant_list: list[str | TGeogPointInst] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.LINEAR, @@ -2208,9 +2101,9 @@ class TGeomPointSeqSet( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, TGeomPointSeq]]] = None, + sequence_list: list[str | TGeomPointSeq] | None = None, normalize: bool = True, _inner=None, ): @@ -2235,9 +2128,9 @@ class TGeogPointSeqSet( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, TGeogPointSeq]]] = None, + sequence_list: list[str | TGeogPointSeq] | None = None, normalize: bool = True, _inner=None, ): diff --git a/pymeos/main/ttext.py b/pymeos/main/ttext.py index d0450abd..e956e732 100644 --- a/pymeos/main/ttext.py +++ b/pymeos/main/ttext.py @@ -1,13 +1,13 @@ from __future__ import annotations from abc import ABC -from typing import Optional, Union, List, Set, overload, TYPE_CHECKING, TypeVar, Type +from typing import TYPE_CHECKING, TypeVar, overload from pymeos_cffi import * from ..collections import * from ..mixins import TTemporallyComparable -from ..temporal import TInterpolation, Temporal, TInstant, TSequence, TSequenceSet +from ..temporal import Temporal, TInstant, TInterpolation, TSequence, TSequenceSet if TYPE_CHECKING: from .tbool import TBool @@ -56,7 +56,7 @@ def from_base_time(value: str, base: datetime) -> TTextInst: ... @staticmethod @overload - def from_base_time(value: str, base: Union[TsTzSet, TsTzSpan]) -> TTextSeq: ... + def from_base_time(value: str, base: TsTzSet | TsTzSpan) -> TTextSeq: ... @staticmethod @overload @@ -79,21 +79,17 @@ def from_base_time(value: str, base: Time) -> TText: ttextseq_from_base_tstzspan, ttextseqset_from_base_tstzspanset """ if isinstance(base, datetime): - return TTextInst( - _inner=ttextinst_make(value, datetime_to_timestamptz(base)) - ) + return TTextInst(_inner=ttextinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TsTzSet): return TTextSeq(_inner=ttextseq_from_base_tstzset(value, base._inner)) elif isinstance(base, TsTzSpan): return TTextSeq(_inner=ttextseq_from_base_tstzspan(value, base._inner)) elif isinstance(base, TsTzSpanSet): - return TTextSeqSet( - _inner=ttextseqset_from_base_tstzspanset(value, base._inner) - ) + return TTextSeqSet(_inner=ttextseqset_from_base_tstzspanset(value, base._inner)) raise TypeError(f"Operation not supported with type {base.__class__}") @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -136,7 +132,7 @@ def as_wkt(self) -> str: return ttext_out(self._inner) # ------------------------- Accessors ------------------------------------- - def value_set(self) -> Set[str]: + def value_set(self) -> set[str]: """ Returns the set of unique values of the temporal string. @@ -236,13 +232,11 @@ def value_at_timestamp(self, timestamp: datetime) -> str: MEOS Functions: ttext_value_at_timestamp """ - result = ttext_value_at_timestamptz( - self._inner, datetime_to_timestamptz(timestamp), True - ) + result = ttext_value_at_timestamptz(self._inner, datetime_to_timestamptz(timestamp), True) return text2cstring(result[0]) # ------------------------- Ever and Always Comparisons ------------------- - def always_less(self, value: Union[str, TText]) -> bool: + def always_less(self, value: str | TText) -> bool: """ Returns whether the values of `self` are always less than `value`. @@ -263,7 +257,7 @@ def always_less(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_less_or_equal(self, value: Union[str, TText]) -> bool: + def always_less_or_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are always less than or equal to `value`. @@ -285,7 +279,7 @@ def always_less_or_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_equal(self, value: Union[str, TText]) -> bool: + def always_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are always equal to `value`. @@ -306,7 +300,7 @@ def always_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_not_equal(self, value: Union[str, TText]) -> bool: + def always_not_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are always not equal to `value`. @@ -327,7 +321,7 @@ def always_not_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_greater_or_equal(self, value: Union[str, TText]) -> bool: + def always_greater_or_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are always greater than or equal to `value`. @@ -349,7 +343,7 @@ def always_greater_or_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def always_greater(self, value: Union[str, TText]) -> bool: + def always_greater(self, value: str | TText) -> bool: """ Returns whether the values of `self` are always greater than `value`. @@ -370,7 +364,7 @@ def always_greater(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_less(self, value: Union[str, TText]) -> bool: + def ever_less(self, value: str | TText) -> bool: """ Returns whether the values of `self` are ever less than `value`. @@ -391,7 +385,7 @@ def ever_less(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_less_or_equal(self, value: Union[str, TText]) -> bool: + def ever_less_or_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are ever less than or equal to `value`. @@ -413,7 +407,7 @@ def ever_less_or_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_equal(self, value: Union[str, TText]) -> bool: + def ever_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are ever equal to `value`. @@ -434,7 +428,7 @@ def ever_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_not_equal(self, value: Union[str, TText]) -> bool: + def ever_not_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are ever not equal to `value`. @@ -455,7 +449,7 @@ def ever_not_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_greater_or_equal(self, value: Union[str, TText]) -> bool: + def ever_greater_or_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are ever greater than or equal to `value`. @@ -477,7 +471,7 @@ def ever_greater_or_equal(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def ever_greater(self, value: Union[str, TText]) -> bool: + def ever_greater(self, value: str | TText) -> bool: """ Returns whether the values of `self` are ever greater than `value`. @@ -498,7 +492,7 @@ def ever_greater(self, value: Union[str, TText]) -> bool: else: raise TypeError(f"Operation not supported with type {value.__class__}") - def never_less(self, value: Union[str, TText]) -> bool: + def never_less(self, value: str | TText) -> bool: """ Returns whether the values of `self` are never less than `value`. @@ -514,7 +508,7 @@ def never_less(self, value: Union[str, TText]) -> bool: """ return not self.ever_less(value) - def never_less_or_equal(self, value: Union[str, TText]) -> bool: + def never_less_or_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are never less than or equal to `value`. @@ -531,7 +525,7 @@ def never_less_or_equal(self, value: Union[str, TText]) -> bool: """ return not self.ever_less_or_equal(value) - def never_equal(self, value: Union[str, TText]) -> bool: + def never_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are never equal to `value`. @@ -547,7 +541,7 @@ def never_equal(self, value: Union[str, TText]) -> bool: """ return not self.ever_equal(value) - def never_not_equal(self, value: Union[str, TText]) -> bool: + def never_not_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are never not equal to `value`. @@ -563,7 +557,7 @@ def never_not_equal(self, value: Union[str, TText]) -> bool: """ return not self.ever_not_equal(value) - def never_greater_or_equal(self, value: Union[str, TText]) -> bool: + def never_greater_or_equal(self, value: str | TText) -> bool: """ Returns whether the values of `self` are never greater than or equal to `value`. @@ -580,7 +574,7 @@ def never_greater_or_equal(self, value: Union[str, TText]) -> bool: """ return not self.ever_greater_or_equal(value) - def never_greater(self, value: Union[str, TText]) -> bool: + def never_greater(self, value: str | TText) -> bool: """ Returns whether the values of `self` are never greater than `value`. @@ -597,7 +591,7 @@ def never_greater(self, value: Union[str, TText]) -> bool: return not self.ever_greater(value) # ------------------------- Temporal Comparisons -------------------------- - def temporal_equal(self, other: Union[str, TText]) -> TBool: + def temporal_equal(self, other: str | TText) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -616,7 +610,7 @@ def temporal_equal(self, other: Union[str, TText]) -> TBool: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[str, TText]) -> TBool: + def temporal_not_equal(self, other: str | TText) -> TBool: """ Returns the temporal not equal relation between `self` and `other`. @@ -635,7 +629,7 @@ def temporal_not_equal(self, other: Union[str, TText]) -> TBool: return super().temporal_not_equal(other) return Temporal._factory(result) - def temporal_less(self, other: Union[str, TText]) -> TBool: + def temporal_less(self, other: str | TText) -> TBool: """ Returns the temporal less than relation between `self` and `other`. @@ -654,7 +648,7 @@ def temporal_less(self, other: Union[str, TText]) -> TBool: return super().temporal_less(other) return Temporal._factory(result) - def temporal_less_or_equal(self, other: Union[str, TText]) -> TBool: + def temporal_less_or_equal(self, other: str | TText) -> TBool: """ Returns the temporal less or equal relation between `self` and `other`. @@ -674,7 +668,7 @@ def temporal_less_or_equal(self, other: Union[str, TText]) -> TBool: return super().temporal_less_or_equal(other) return Temporal._factory(result) - def temporal_greater(self, other: Union[str, TText]) -> TBool: + def temporal_greater(self, other: str | TText) -> TBool: """ Returns the temporal greater than relation between `self` and `other`. @@ -694,7 +688,7 @@ def temporal_greater(self, other: Union[str, TText]) -> TBool: return super().temporal_greater(other) return Temporal._factory(result) - def temporal_greater_or_equal(self, other: Union[str, TText]) -> TBool: + def temporal_greater_or_equal(self, other: str | TText) -> TBool: """ Returns the temporal greater or equal relation between `self` and `other`. @@ -716,9 +710,7 @@ def temporal_greater_or_equal(self, other: Union[str, TText]) -> TBool: return Temporal._factory(result) # ------------------------- Restrictions ---------------------------------- - def at( - self, other: Union[str, List[str], datetime, TsTzSet, TsTzSpan, TsTzSpanSet] - ) -> TText: + def at(self, other: str | list[str] | datetime | TsTzSet | TsTzSpan | TsTzSpanSet) -> TText: """ Returns a new temporal string with the values of `self` restricted to the time or value `other`. @@ -741,9 +733,7 @@ def at( return super().at(other) return Temporal._factory(result) - def minus( - self, other: Union[str, List[str], datetime, TsTzSet, TsTzSpan, TsTzSpanSet] - ) -> TText: + def minus(self, other: str | list[str] | datetime | TsTzSet | TsTzSpan | TsTzSpanSet) -> TText: """ Returns a new temporal string with the values of `self` restricted to the complement of the time or value `other`. @@ -768,7 +758,7 @@ def minus( return Temporal._factory(result) # ------------------------- Text Operations ------------------------------ - def concatenate(self, other: Union[str, TText], other_before: bool = False): + def concatenate(self, other: str | TText, other_before: bool = False): """ Returns a new temporal string with the values of `self` concatenated with the values of `other`. @@ -787,9 +777,7 @@ def concatenate(self, other: Union[str, TText], other_before: bool = False): """ if isinstance(other, str): result = ( - textcat_ttext_text(self._inner, other) - if not other_before - else textcat_text_ttext(other, self._inner) + textcat_ttext_text(self._inner, other) if not other_before else textcat_text_ttext(other, self._inner) ) elif isinstance(other, TText): result = ( @@ -865,10 +853,10 @@ class TTextInst(TInstant[str, "TText", "TTextInst", "TTextSeq", "TTextSeqSet"], def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - value: Optional[str] = None, - timestamp: Optional[Union[str, datetime]] = None, + value: str | None = None, + timestamp: str | datetime | None = None, _inner=None, ): super().__init__(string=string, value=value, timestamp=timestamp, _inner=_inner) @@ -883,9 +871,9 @@ class TTextSeq(TSequence[str, "TText", "TTextInst", "TTextSeq", "TTextSeqSet"], def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, TTextInst]]] = None, + instant_list: list[str | TTextInst] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.STEPWISE, @@ -903,9 +891,7 @@ def __init__( ) -class TTextSeqSet( - TSequenceSet[str, "TText", "TTextInst", "TTextSeq", "TTextSeqSet"], TText -): +class TTextSeqSet(TSequenceSet[str, "TText", "TTextInst", "TTextSeq", "TTextSeqSet"], TText): """ Class for representing temporal strings over a tstzspan of time with gaps. """ @@ -914,9 +900,9 @@ class TTextSeqSet( def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, TTextSeq]]] = None, + sequence_list: list[str | TTextSeq] | None = None, normalize: bool = True, _inner=None, ): diff --git a/pymeos/meos_init.py b/pymeos/meos_init.py index f02ed68f..d2884852 100644 --- a/pymeos/meos_init.py +++ b/pymeos/meos_init.py @@ -1,17 +1,17 @@ -from typing import Optional, Union, Tuple, Any +from typing import Any from pymeos_cffi import ( - meos_initialize, meos_finalize, + meos_initialize, meos_set_datestyle, meos_set_intervalstyle, ) def pymeos_initialize( - timezone: Optional[str] = None, - date_style: Union[None, str, Tuple[str, Any]] = None, - interval_style: Union[None, str, Tuple[str, int]] = None, + timezone: str | None = None, + date_style: None | str | tuple[str, Any] = None, + interval_style: None | str | tuple[str, int] = None, ) -> None: """ Initializes the underlying MEOS platform. diff --git a/pymeos/mixins/__init__.py b/pymeos/mixins/__init__.py index 0d9da5d6..cf55cde0 100644 --- a/pymeos/mixins/__init__.py +++ b/pymeos/mixins/__init__.py @@ -1,3 +1,10 @@ -from .simplify import TSimplifiable from .comparison import TComparable -from .temporal_comparison import TTemporallyEquatable, TTemporallyComparable +from .simplify import TSimplifiable +from .temporal_comparison import TTemporallyComparable, TTemporallyEquatable + +__all__ = [ + "TComparable", + "TSimplifiable", + "TTemporallyComparable", + "TTemporallyEquatable", +] diff --git a/pymeos/mixins/comparison.py b/pymeos/mixins/comparison.py index 5e82a57c..d2c1d5bd 100644 --- a/pymeos/mixins/comparison.py +++ b/pymeos/mixins/comparison.py @@ -1,14 +1,16 @@ -from typing import TypeVar +from typing import Any, TypeVar from pymeos_cffi import ( temporal_eq, - temporal_ne, - temporal_lt, - temporal_le, - temporal_gt, temporal_ge, + temporal_gt, + temporal_le, + temporal_lt, + temporal_ne, ) +from ..temporal import Temporal + Self = TypeVar("Self", bound="Temporal[Any]") diff --git a/pymeos/mixins/simplify.py b/pymeos/mixins/simplify.py index 711c24c5..1993e0f6 100644 --- a/pymeos/mixins/simplify.py +++ b/pymeos/mixins/simplify.py @@ -1,14 +1,16 @@ from datetime import timedelta -from typing import TypeVar +from typing import Any, TypeVar from pymeos_cffi import ( + temporal_simplify_dp, + temporal_simplify_max_dist, temporal_simplify_min_dist, temporal_simplify_min_tdelta, timedelta_to_interval, - temporal_simplify_dp, - temporal_simplify_max_dist, ) +from ..temporal import Temporal + Self = TypeVar("Self", bound="Temporal[Any]") @@ -46,9 +48,7 @@ def simplify_min_tdelta(self: Self, distance: timedelta) -> Self: delta = timedelta_to_interval(distance) return self.__class__(_inner=temporal_simplify_min_tdelta(self._inner, delta)) - def simplify_douglas_peucker( - self: Self, distance: float, synchronized: bool = False - ) -> Self: + def simplify_douglas_peucker(self: Self, distance: float, synchronized: bool = False) -> Self: """ Simplifies a temporal value using the Douglas-Peucker line simplification algorithm. @@ -64,13 +64,9 @@ def simplify_douglas_peucker( MEOS Functions: temporal_simplify_dp """ - return self.__class__( - _inner=temporal_simplify_dp(self._inner, distance, synchronized) - ) + return self.__class__(_inner=temporal_simplify_dp(self._inner, distance, synchronized)) - def simplify_max_distance( - self: Self, distance: float, synchronized: bool = False - ) -> Self: + def simplify_max_distance(self: Self, distance: float, synchronized: bool = False) -> Self: """ Simplifies a temporal value using a single-pass Douglas-Peucker line simplification algorithm. @@ -86,6 +82,4 @@ def simplify_max_distance( MEOS Functions: temporal_simplify_max_dist """ - return self.__class__( - _inner=temporal_simplify_max_dist(self._inner, distance, synchronized) - ) + return self.__class__(_inner=temporal_simplify_max_dist(self._inner, distance, synchronized)) diff --git a/pymeos/mixins/temporal_comparison.py b/pymeos/mixins/temporal_comparison.py index 2c8c8397..2594d54d 100644 --- a/pymeos/mixins/temporal_comparison.py +++ b/pymeos/mixins/temporal_comparison.py @@ -1,14 +1,14 @@ from __future__ import annotations -from typing import TypeVar, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, TypeVar from pymeos_cffi import ( teq_temporal_temporal, - tne_temporal_temporal, - tlt_temporal_temporal, - tle_temporal_temporal, - tgt_temporal_temporal, tge_temporal_temporal, + tgt_temporal_temporal, + tle_temporal_temporal, + tlt_temporal_temporal, + tne_temporal_temporal, ) Self = TypeVar("Self", bound="Temporal[Any]") diff --git a/pymeos/plotters/__init__.py b/pymeos/plotters/__init__.py index 358bfa6e..f7a50141 100644 --- a/pymeos/plotters/__init__.py +++ b/pymeos/plotters/__init__.py @@ -5,3 +5,13 @@ from .sequence_plotter import TemporalSequencePlotter from .sequenceset_plotter import TemporalSequenceSetPlotter from .time_plotter import TimePlotter + +__all__ = [ + "BoxPlotter", + "TemporalPointSequencePlotter", + "TemporalPointSequenceSetPlotter", + "SpanPlotter", + "TemporalSequencePlotter", + "TemporalSequenceSetPlotter", + "TimePlotter", +] diff --git a/pymeos/plotters/box_plotter.py b/pymeos/plotters/box_plotter.py index 009e0e00..e26bd3d4 100644 --- a/pymeos/plotters/box_plotter.py +++ b/pymeos/plotters/box_plotter.py @@ -1,8 +1,8 @@ from matplotlib import pyplot as plt +from ..boxes import STBox, TBox from .range_plotter import SpanPlotter from .time_plotter import TimePlotter -from ..boxes import TBox, STBox class BoxPlotter: @@ -28,13 +28,9 @@ def plot_tbox(tbox: TBox, *args, axes=None, **kwargs): :func:`~pymeos.plotters.time_plotter.TimePlotter.plot_tstzspan` """ if not tbox.has_t: - return SpanPlotter.plot_span( - tbox.to_floatspan(), *args, axes=axes, **kwargs - ) + return SpanPlotter.plot_span(tbox.to_floatspan(), *args, axes=axes, **kwargs) if not tbox.has_x: - return TimePlotter.plot_tstzspan( - tbox.to_tstzspan(), *args, axes=axes, **kwargs - ) + return TimePlotter.plot_tstzspan(tbox.to_tstzspan(), *args, axes=axes, **kwargs) return BoxPlotter._plot_box( tbox.tmin(), tbox.tmax(), @@ -161,9 +157,7 @@ def _plot_box( return_array = [plot] if draw_filling: - f = base.fill_between( - [xmin, xmax], [ymax, ymax], [ymin, ymin], *args, alpha=0.3, **kwargs - ) + f = base.fill_between([xmin, xmax], [ymax, ymax], [ymin, ymin], *args, alpha=0.3, **kwargs) return_array.append(f) if rotate_xticks: diff --git a/pymeos/plotters/point_sequence_plotter.py b/pymeos/plotters/point_sequence_plotter.py index 626577cd..483b6aba 100644 --- a/pymeos/plotters/point_sequence_plotter.py +++ b/pymeos/plotters/point_sequence_plotter.py @@ -1,8 +1,6 @@ -from typing import Union, List - import matplotlib.pyplot as plt -from ..main import TPointSeq, TPointInst +from ..main import TPointInst, TPointSeq from ..temporal import TInterpolation @@ -13,7 +11,7 @@ class TemporalPointSequencePlotter: @staticmethod def plot_xy( - sequence: Union[TPointSeq, List[TPointInst]], + sequence: TPointSeq | list[TPointInst], *args, axes=None, show_markers=True, @@ -46,9 +44,7 @@ def plot_xy( else: plot_func = base.scatter - ins: list[TPointInst] = ( - sequence.instants() if isinstance(sequence, TPointSeq) else sequence - ) + ins: list[TPointInst] = sequence.instants() if isinstance(sequence, TPointSeq) else sequence x = [i.x().value() for i in ins] y = [i.y().value() for i in ins] @@ -88,7 +84,7 @@ def plot_xy( return plots @staticmethod - def plot_sequences_xy(sequences: List[TPointSeq], *args, **kwargs): + def plot_sequences_xy(sequences: list[TPointSeq], *args, **kwargs): """ Plot a list of TPointSeq on the given axes. Every sequence will be plotted in a different color. diff --git a/pymeos/plotters/point_sequenceset_plotter.py b/pymeos/plotters/point_sequenceset_plotter.py index bff106f7..b39ea216 100644 --- a/pymeos/plotters/point_sequenceset_plotter.py +++ b/pymeos/plotters/point_sequenceset_plotter.py @@ -1,8 +1,6 @@ -from typing import Union, List - -from .point_sequence_plotter import TemporalPointSequencePlotter from .. import TPointSeq from ..main import TPointSeqSet +from .point_sequence_plotter import TemporalPointSequencePlotter class TemporalPointSequenceSetPlotter: @@ -11,7 +9,7 @@ class TemporalPointSequenceSetPlotter: """ @staticmethod - def plot_xy(sequence_set: Union[TPointSeqSet, List[TPointSeq]], *args, **kwargs): + def plot_xy(sequence_set: TPointSeqSet | list[TPointSeq], *args, **kwargs): """ Plot a TPointSeqSet or a list of TPointSeq on the given axes. Every sequence in the set will be plotted with the same color. @@ -28,11 +26,7 @@ def plot_xy(sequence_set: Union[TPointSeqSet, List[TPointSeq]], *args, **kwargs) :func:`~pymeos.plotters.point_sequence_plotter.TemporalPointSequencePlotter.plot_xy`, :func:`~pymeos.plotters.point_sequence_plotter.TemporalPointSequencePlotter.plot_sequences_xy` """ - seqs = ( - sequence_set.sequences() - if isinstance(sequence_set, TPointSeqSet) - else sequence_set - ) + seqs = sequence_set.sequences() if isinstance(sequence_set, TPointSeqSet) else sequence_set plots = [TemporalPointSequencePlotter.plot_xy(seqs[0], *args, **kwargs)] if "color" not in kwargs: kwargs["color"] = plots[0][0][0].get_color() diff --git a/pymeos/plotters/range_plotter.py b/pymeos/plotters/range_plotter.py index bae28dcc..4b188605 100644 --- a/pymeos/plotters/range_plotter.py +++ b/pymeos/plotters/range_plotter.py @@ -1,7 +1,6 @@ -from typing import Union - from matplotlib import pyplot as plt -from pymeos import IntSpan, FloatSpan + +from pymeos import FloatSpan, IntSpan class SpanPlotter: @@ -10,7 +9,7 @@ class SpanPlotter: """ @staticmethod - def plot_span(span: Union[IntSpan, FloatSpan], *args, axes=None, **kwargs): + def plot_span(span: IntSpan | FloatSpan, *args, axes=None, **kwargs): """ Plot a :class:`FloatSpan` or :class:`IntSpan` on the given axes. @@ -24,12 +23,8 @@ def plot_span(span: Union[IntSpan, FloatSpan], *args, axes=None, **kwargs): List with the plotted elements. """ base = axes or plt.gca() - ll = base.axhline( - span.lower(), *args, linestyle="-" if span.lower_inc() else "--", **kwargs - ) + ll = base.axhline(span.lower(), *args, linestyle="-" if span.lower_inc() else "--", **kwargs) kwargs.pop("label", None) - ul = base.axhline( - span.upper(), *args, linestyle="-" if span.upper_inc() else "--", **kwargs - ) + ul = base.axhline(span.upper(), *args, linestyle="-" if span.upper_inc() else "--", **kwargs) s = base.axhspan(span.lower(), span.upper(), *args, alpha=0.3, **kwargs) return [ll, ul, s] diff --git a/pymeos/plotters/sequence_plotter.py b/pymeos/plotters/sequence_plotter.py index 609eeb05..b073198c 100644 --- a/pymeos/plotters/sequence_plotter.py +++ b/pymeos/plotters/sequence_plotter.py @@ -1,9 +1,8 @@ from functools import partial -from typing import Union, List import matplotlib.pyplot as plt -from ..temporal import TSequence, TInterpolation, TInstant +from ..temporal import TInstant, TInterpolation, TSequence class TemporalSequencePlotter: @@ -13,7 +12,7 @@ class TemporalSequencePlotter: @staticmethod def plot( - sequence: Union[TSequence, List[TInstant]], + sequence: TSequence | list[TInstant], *args, axes=None, show_markers=True, @@ -92,7 +91,7 @@ def plot( return plots @staticmethod - def plot_sequences(sequences: List[TSequence], *args, **kwargs): + def plot_sequences(sequences: list[TSequence], *args, **kwargs): """ Plot a list of :class:`TSequence` on the given axes. Every sequence will be plotted in a different color. diff --git a/pymeos/plotters/sequenceset_plotter.py b/pymeos/plotters/sequenceset_plotter.py index c9aa70e9..57742429 100644 --- a/pymeos/plotters/sequenceset_plotter.py +++ b/pymeos/plotters/sequenceset_plotter.py @@ -1,8 +1,6 @@ -from typing import List, Union - -from .sequence_plotter import TemporalSequencePlotter from .. import TSequence from ..temporal import TSequenceSet +from .sequence_plotter import TemporalSequencePlotter class TemporalSequenceSetPlotter: @@ -11,7 +9,7 @@ class TemporalSequenceSetPlotter: """ @staticmethod - def plot(sequence_set: Union[TSequenceSet, List[TSequence]], *args, **kwargs): + def plot(sequence_set: TSequenceSet | list[TSequence], *args, **kwargs): """ Plot a :class:`TSequenceSet` or a list of :class:`TSequence` on the given axes. Every sequence in the set will be plotted with the same color. @@ -28,11 +26,7 @@ def plot(sequence_set: Union[TSequenceSet, List[TSequence]], *args, **kwargs): :func:`~pymeos.plotters.sequence_plotter.TemporalSequencePlotter.plot` """ - seqs = ( - sequence_set.sequences() - if isinstance(sequence_set, TSequenceSet) - else sequence_set - ) + seqs = sequence_set.sequences() if isinstance(sequence_set, TSequenceSet) else sequence_set plots = [TemporalSequencePlotter.plot(seqs[0], *args, **kwargs)] if "color" not in kwargs: pl = plots[0] diff --git a/pymeos/plotters/time_plotter.py b/pymeos/plotters/time_plotter.py index 98539aec..cb1ccb8b 100644 --- a/pymeos/plotters/time_plotter.py +++ b/pymeos/plotters/time_plotter.py @@ -1,10 +1,8 @@ from datetime import datetime -from typing import Union from matplotlib import pyplot as plt from ..collections import TsTzSet, TsTzSpan, TsTzSpanSet -from ..collections.time.dateset import DateSet class TimePlotter: diff --git a/pymeos/temporal/interpolation.py b/pymeos/temporal/interpolation.py index c3f18a50..7f6ac58d 100644 --- a/pymeos/temporal/interpolation.py +++ b/pymeos/temporal/interpolation.py @@ -1,7 +1,9 @@ from __future__ import annotations -from pymeos_cffi import InterpolationType + from enum import IntEnum +from pymeos_cffi import InterpolationType + class TInterpolation(IntEnum): """ @@ -27,6 +29,8 @@ def to_string(self) -> str: return "Step" elif self == InterpolationType.LINEAR: return "Linear" + else: + raise ValueError() @staticmethod def from_string(source: str, none: bool = True) -> TInterpolation: diff --git a/pymeos/temporal/temporal.py b/pymeos/temporal/temporal.py index cff0ea32..b168ae66 100644 --- a/pymeos/temporal/temporal.py +++ b/pymeos/temporal/temporal.py @@ -1,19 +1,20 @@ from __future__ import annotations from abc import ABC, abstractmethod -from typing import Optional, List, Union, TYPE_CHECKING, Set, Generic, TypeVar, Type +from typing import TYPE_CHECKING, Generic, TypeVar from pymeos_cffi import * -from .interpolation import TInterpolation from ..collections import * from ..mixins import TComparable, TTemporallyEquatable +from .interpolation import TInterpolation if TYPE_CHECKING: + import pandas as pd + + from ..boxes import Box from .tinstant import TInstant from .tsequence import TSequence - from ..boxes import Box - import pandas as pd def import_pandas(): @@ -48,12 +49,17 @@ class Temporal(Generic[TBase, TG, TI, TS, TSS], TComparable, TTemporallyEquatabl ComponentClass = None """ - Class of the components, for example, + Class of the components, for example, 1. ``TFloatInst`` for both ``TFloatInst`` and ``TFloatSeq`` 2. ``TFloatSeq`` for ``TFloatSeqSet``. """ + DefaultInterpolation: TInterpolation = TInterpolation.STEPWISE + """ + Default interpolation of the class. + """ + _parse_function = None # ------------------------- Constructors ---------------------------------- @@ -78,7 +84,7 @@ def __str__(self) -> str: pass def __repr__(self) -> str: - return f"{self.__class__.__name__}" f"({self})" + return f"{self.__class__.__name__}({self})" @staticmethod @abstractmethod @@ -98,7 +104,7 @@ def from_base_time(value: TBase, base: Time) -> TG: @classmethod @abstractmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + def from_mfjson(cls: type[Self], mfjson: str) -> Self: """ Returns a temporal object from a MF-JSON string. @@ -111,7 +117,7 @@ def from_mfjson(cls: Type[Self], mfjson: str) -> Self: pass @classmethod - def from_wkb(cls: Type[Self], wkb: bytes) -> Self: + def from_wkb(cls: type[Self], wkb: bytes) -> Self: """ Returns a temporal object from WKB bytes. @@ -128,7 +134,7 @@ def from_wkb(cls: Type[Self], wkb: bytes) -> Self: return Temporal._factory(result) @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: + def from_hexwkb(cls: type[Self], hexwkb: str) -> Self: """ Returns a temporal object from a hex-encoded WKB string. @@ -145,7 +151,7 @@ def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: return Temporal._factory(result) @classmethod - def from_merge(cls: Type[Self], *temporals: TG) -> Self: + def from_merge(cls: type[Self], *temporals: TG) -> Self: """ Returns a temporal object that is the result of merging the given temporal objects. @@ -165,7 +171,7 @@ def from_merge(cls: Type[Self], *temporals: TG) -> Self: return Temporal._factory(result) @classmethod - def from_merge_array(cls: Type[Self], temporals: List[TG]) -> Self: + def from_merge_array(cls: type[Self], temporals: list[TG]) -> Self: """ Returns a temporal object that is the result of merging the given temporal objects. @@ -197,7 +203,7 @@ def as_mfjson( with_bbox: bool = True, flags: int = 3, precision: int = 6, - srs: Optional[str] = None, + srs: str | None = None, ) -> str: """ Returns the temporal object as a MF-JSON string. @@ -241,7 +247,7 @@ def as_hexwkb(self) -> str: return temporal_as_hexwkb(self._inner, 4)[0] # ------------------------- Accessors ------------------------------------- - def bounding_box(self) -> Union[TsTzSpan, Box]: + def bounding_box(self) -> TsTzSpan | Box: """ Returns the bounding box of `self`. @@ -264,13 +270,13 @@ def interpolation(self) -> TInterpolation: return TInterpolation.from_string(val) @abstractmethod - def value_set(self) -> Set[TBase]: + def value_set(self) -> set[TBase]: """ Returns the unique values in `self`. """ pass - def values(self) -> List[TBase]: + def values(self) -> list[TBase]: """ Returns the list of values taken by `self`. """ @@ -420,7 +426,7 @@ def instant_n(self, n: int) -> TI: return _TemporalFactory.create_temporal(temporal_instant_n(self._inner, n + 1)) - def instants(self) -> List[TI]: + def instants(self) -> list[TI]: """ Returns the instants in `self`. @@ -468,7 +474,7 @@ def timestamp_n(self, n: int) -> datetime: """ return timestamptz_to_datetime(temporal_timestamptz_n(self._inner, n + 1)) - def timestamps(self) -> List[datetime]: + def timestamps(self) -> list[datetime]: """ Returns the timestamps in `self`. @@ -478,7 +484,7 @@ def timestamps(self) -> List[datetime]: ts, count = temporal_timestamps(self._inner) return [timestamptz_to_datetime(ts[i]) for i in range(count)] - def segments(self) -> List[TS]: + def segments(self) -> list[TS]: """ Returns the temporal segments in `self`. @@ -543,9 +549,7 @@ def scale_time(self, duration: timedelta) -> Self: scaled = temporal_scale_time(self._inner, timedelta_to_interval(duration)) return Temporal._factory(scaled) - def shift_scale_time( - self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None - ) -> Self: + def shift_scale_time(self, shift: timedelta | None = None, duration: timedelta | None = None) -> Self: """ Returns a new :class:`Temporal` with the time dimension shifted by ``shift`` and scaled so the temporal dimension has duration @@ -559,9 +563,7 @@ def shift_scale_time( MEOS Functions: temporal_shift_scale_time """ - assert ( - shift is not None or duration is not None - ), "shift and duration must not be both None" + assert shift is not None or duration is not None, "shift and duration must not be both None" scaled = temporal_shift_scale_time( self._inner, timedelta_to_interval(shift) if shift else None, @@ -571,9 +573,9 @@ def shift_scale_time( def temporal_sample( self, - duration: Union[str, timedelta], - start: Optional[Union[str, datetime]] = None, - interpolation: Optional[TInterpolation] = None, + duration: str | timedelta, + start: str | datetime | None = None, + interpolation: TInterpolation | None = None, ) -> TG: """ Returns a new :class:`Temporal` downsampled with respect to ``duration``. @@ -608,8 +610,8 @@ def temporal_sample( def temporal_precision( self, - duration: Union[str, timedelta], - start: Optional[Union[str, datetime]] = None, + duration: str | timedelta, + start: str | datetime | None = None, ) -> TG: """ Returns a new :class:`Temporal` with precision reduced to ``duration``. @@ -654,7 +656,7 @@ def to_sequence(self, interpolation: TInterpolation) -> TS: MEOS Functions: temporal_to_sequence """ - seq = temporal_to_tsequence(self._inner, interpolation.to_string()) + seq = temporal_to_tsequence(self._inner, interpolation) return Temporal._factory(seq) def to_sequenceset(self, interpolation: TInterpolation) -> TSS: @@ -664,7 +666,7 @@ def to_sequenceset(self, interpolation: TInterpolation) -> TSS: MEOS Functions: temporal_to_tsequenceset """ - ss = temporal_to_tsequenceset(self._inner, interpolation.to_string()) + ss = temporal_to_tsequenceset(self._inner, interpolation) return Temporal._factory(ss) def to_dataframe(self) -> pd.DataFrame: @@ -680,8 +682,9 @@ def to_dataframe(self) -> pd.DataFrame: def append_instant( self, instant: TInstant[TBase], - max_dist: Optional[float] = 0.0, - max_time: Optional[timedelta] = None, + max_dist: float | None = 0.0, + max_time: timedelta | None = None, + default_interpolation: TInterpolation = TInterpolation.NONE, ) -> TG: """ Returns a new :class:`Temporal` object equal to `self` with `instant` @@ -691,6 +694,8 @@ def append_instant( instant: :class:`TInstant` to append max_dist: Maximum distance for defining a gap max_time: Maximum time for defining a gap + default_interpolation: Default interpolation to use when appending an instant to another instant. This is + only used when `self` is an instant and ignored otherwise. MEOS Functions: temporal_append_tinstant @@ -699,9 +704,10 @@ def append_instant( interv = None else: interv = timedelta_to_interval(max_time) - new_inner = temporal_append_tinstant( - self._inner, instant._inner, max_dist, interv, False - ) + interpolation = self.interpolation() + if interpolation == TInterpolation.NONE: + interpolation = self.DefaultInterpolation + new_inner = temporal_append_tinstant(self._inner, instant._inner, interpolation, max_dist, interv, False) return Temporal._factory(new_inner) def append_sequence(self, sequence: TSequence[TBase]) -> TG: @@ -718,9 +724,7 @@ def append_sequence(self, sequence: TSequence[TBase]) -> TG: new_inner = temporal_append_tsequence(self._inner, sequence._inner, False) return Temporal._factory(new_inner) - def merge( - self, other: Union[type(None), Temporal[TBase], List[Temporal[TBase]]] - ) -> TG: + def merge(self, other: type(None) | Temporal[TBase] | list[Temporal[TBase]]) -> TG: """ Returns a new :class:`Temporal` object that is the result of merging `self` with `other`. @@ -733,9 +737,7 @@ def merge( elif isinstance(other, Temporal): new_temp = temporal_merge(self._inner, other._inner) elif isinstance(other, list): - new_temp = temporal_merge_array( - [self._inner, *(o._inner for o in other)], len(other) + 1 - ) + new_temp = temporal_merge_array([self._inner, *(o._inner for o in other)], len(other) + 1) else: raise TypeError(f"Operation not supported with type {other.__class__}") return Temporal._factory(new_temp) @@ -790,9 +792,7 @@ def delete(self, other: Time, connect: bool = True) -> TG: temporal_update """ if isinstance(other, datetime): - new_inner = temporal_delete_timestamptz( - self._inner, datetime_to_timestamptz(other), connect - ) + new_inner = temporal_delete_timestamptz(self._inner, datetime_to_timestamptz(other), connect) elif isinstance(other, TsTzSet): new_inner = temporal_delete_tstzset(self._inner, other._inner, connect) elif isinstance(other, TsTzSpan): @@ -822,9 +822,7 @@ def at(self, other: Time) -> TG: temporal_at_tstzspan, temporal_at_tstzspanset """ if isinstance(other, datetime): - result = temporal_at_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = temporal_at_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TsTzSet): result = temporal_at_tstzset(self._inner, other._inner) elif isinstance(other, TsTzSpan): @@ -883,9 +881,7 @@ def minus(self, other: Time) -> TG: elif isinstance(other, TsTzSpanSet): result = temporal_minus_tstzspanset(self._inner, other._inner) elif isinstance(other, datetime): - result = temporal_minus_timestamptz( - self._inner, datetime_to_timestamptz(other) - ) + result = temporal_minus_timestamptz(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TsTzSet): result = temporal_minus_tstzset(self._inner, other._inner) else: @@ -921,7 +917,7 @@ def minus_max(self) -> TG: return Temporal._factory(result) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: + def is_adjacent(self, other: Time | Temporal | Box) -> bool: """ Returns whether the bounding box of `self` is adjacent to the bounding box of `other`. Temporal subclasses may override this method to provide @@ -939,7 +935,7 @@ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.bounding_box().is_adjacent(other) - def is_temporally_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: + def is_temporally_adjacent(self, other: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` is temporally adjacent to the bounding tstzspan of `other`. @@ -955,7 +951,7 @@ def is_temporally_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.tstzspan().is_adjacent(other) - def is_contained_in(self, container: Union[Time, Temporal, Box]) -> bool: + def is_contained_in(self, container: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` is contained in the bounding tstzspan of `container`. Temporal subclasses may override this @@ -972,7 +968,7 @@ def is_contained_in(self, container: Union[Time, Temporal, Box]) -> bool: """ return self.bounding_box().is_contained_in(container) - def is_temporally_contained_in(self, container: Union[Time, Temporal, Box]) -> bool: + def is_temporally_contained_in(self, container: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` is contained in the bounding tstzspan of `container`. @@ -988,7 +984,7 @@ def is_temporally_contained_in(self, container: Union[Time, Temporal, Box]) -> b """ return self.tstzspan().is_contained_in(container) - def contains(self, content: Union[Time, Temporal, Box]) -> bool: + def contains(self, content: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` contains the bounding tstzspan of `content`. Temporal subclasses may override this method to @@ -1021,7 +1017,7 @@ def __contains__(self, item): """ return self.contains(item) - def temporally_contains(self, content: Union[Time, Temporal, Box]) -> bool: + def temporally_contains(self, content: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` contains the bounding tstzspan of `content`. @@ -1037,7 +1033,7 @@ def temporally_contains(self, content: Union[Time, Temporal, Box]) -> bool: """ return self.tstzspan().contains(content) - def overlaps(self, other: Union[Time, Temporal, Box]) -> bool: + def overlaps(self, other: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` overlaps the bounding tstzspan of `other`. Temporal subclasses may override this method to @@ -1054,7 +1050,7 @@ def overlaps(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.bounding_box().overlaps(other) - def temporally_overlaps(self, other: Union[Time, Temporal, Box]) -> bool: + def temporally_overlaps(self, other: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` overlaps the bounding tstzspan of `other`. @@ -1070,7 +1066,7 @@ def temporally_overlaps(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.tstzspan().overlaps(other) - def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + def is_same(self, other: Time | Temporal | Box) -> bool: """ Returns whether the bounding tstzspan of `self` is the same as the bounding tstzspan of `other`. Temporal subclasses may override this @@ -1088,7 +1084,7 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: return self.bounding_box().is_same(other) # ------------------------- Position Operations --------------------------- - def is_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_before(self, other: Time | Temporal | Box) -> bool: """ Returns whether `self` is before `other`. @@ -1103,7 +1099,7 @@ def is_before(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.tstzspan().is_before(other) - def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_before(self, other: Time | Temporal | Box) -> bool: """ Returns whether `self` is before `other` allowing overlap. That is, `self` doesn't extend after `other`. @@ -1119,7 +1115,7 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.tstzspan().is_over_or_before(other) - def is_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_after(self, other: Time | Temporal | Box) -> bool: """ Returns whether `self` is after `other`. @@ -1134,7 +1130,7 @@ def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.tstzspan().is_after(other) - def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_after(self, other: Time | Temporal | Box) -> bool: """ Returns whether `self` is after `other` allowing overlap. That is, `self` doesn't extend before `other`. @@ -1199,9 +1195,9 @@ def hausdorff_distance(self, other: Temporal) -> float: # ------------------------- Split Operations ------------------------------ def time_split( self, - duration: Union[str, timedelta], - start: Optional[Union[str, datetime]] = None, - ) -> List[TG]: + duration: str | timedelta, + start: str | datetime | None = None, + ) -> list[TG]: """ Returns a list of temporal objects of the same subtype as `self` with the same values as `self` but split in temporal tiles of duration @@ -1223,22 +1219,14 @@ def time_split( if start is None: st = pg_timestamptz_in("2000-01-03", -1) else: - st = ( - datetime_to_timestamptz(start) - if isinstance(start, datetime) - else pg_timestamptz_in(start, -1) - ) - dt = ( - timedelta_to_interval(duration) - if isinstance(duration, timedelta) - else pg_interval_in(duration, -1) - ) + st = datetime_to_timestamptz(start) if isinstance(start, datetime) else pg_timestamptz_in(start, -1) + dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) else pg_interval_in(duration, -1) fragments, times, count = temporal_time_split(self._inner, dt, st) from ..factory import _TemporalFactory return [_TemporalFactory.create_temporal(fragments[i]) for i in range(count)] - def time_split_n(self, n: int) -> List[TG]: + def time_split_n(self, n: int) -> list[TG]: """ Returns a list of temporal objects of the same subtype as `self` with the same values as `self` but split in n temporal tiles of equal @@ -1264,8 +1252,8 @@ def time_split_n(self, n: int) -> List[TG]: def stops( self, - max_distance: Optional[float] = 0.0, - min_duration: Optional[timedelta] = timedelta(), + max_distance: float | None = 0.0, + min_duration: timedelta | None = None, ) -> TSS: """ Return the subsequences where the objects stay within an area with a @@ -1282,9 +1270,8 @@ def stops( MEOS Functions: temporal_stops """ - new_inner = temporal_stops( - self._inner, max_distance, timedelta_to_interval(min_duration) - ) + min_duration = min_duration or timedelta() + new_inner = temporal_stops(self._inner, max_distance, timedelta_to_interval(min_duration)) from ..factory import _TemporalFactory return _TemporalFactory.create_temporal(new_inner) diff --git a/pymeos/temporal/tinstant.py b/pymeos/temporal/tinstant.py index 08f6c207..d79ffbce 100644 --- a/pymeos/temporal/tinstant.py +++ b/pymeos/temporal/tinstant.py @@ -2,7 +2,7 @@ from abc import ABC from datetime import datetime -from typing import Optional, Union, TypeVar, List +from typing import TypeVar from pymeos_cffi import * @@ -29,15 +29,15 @@ class TInstant(Temporal[TBase, TG, TI, TS, TSS], ABC): def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - value: Optional[Union[str, TBase]] = None, - timestamp: Optional[Union[str, datetime]] = None, + value: str | TBase | None = None, + timestamp: str | datetime | None = None, _inner=None, ): - assert (_inner is not None) or ( - (string is not None) != (value is not None and timestamp is not None) - ), "Either string must be not None or both point and timestamp must be not" + assert (_inner is not None) or ((string is not None) != (value is not None and timestamp is not None)), ( + "Either string must be not None or both point and timestamp must be not" + ) if _inner is not None: self._inner = as_tinstant(_inner) elif string is not None: @@ -48,9 +48,7 @@ def __init__( if isinstance(timestamp, datetime) else pg_timestamptz_in(timestamp, -1) ) - self._inner = self.__class__._make_function( - self.__class__._cast_function(value), ts - ) + self._inner = self.__class__._make_function(self.__class__._cast_function(value), ts) def value(self) -> TBase: """ @@ -87,7 +85,7 @@ def instant_n(self: Self, n: int) -> Self: else: raise Exception("ERROR: Out of range") - def instants(self: Self) -> List[Self]: + def instants(self: Self) -> list[Self]: return [self] def start_timestamp(self) -> datetime: @@ -102,5 +100,5 @@ def timestamp_n(self, n) -> datetime: else: raise Exception("ERROR: Out of range") - def timestamps(self) -> List[datetime]: + def timestamps(self) -> list[datetime]: return [self.timestamp()] diff --git a/pymeos/temporal/tsequence.py b/pymeos/temporal/tsequence.py index 35578ccc..77587217 100644 --- a/pymeos/temporal/tsequence.py +++ b/pymeos/temporal/tsequence.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC -from typing import Optional, Union, List, Any, TypeVar, Type +from typing import Any, TypeVar from pymeos_cffi import * @@ -25,29 +25,25 @@ class TSequence(Temporal[TBase, TG, TI, TS, TSS], ABC): # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - instant_list: Optional[List[Union[str, Any]]] = None, + instant_list: list[str | Any] | None = None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.LINEAR, normalize: bool = True, _inner=None, ): - assert (_inner is not None) or ( - (string is not None) != (instant_list is not None) - ), "Either string must be not None or instant_list must be not" + assert (_inner is not None) or ((string is not None) != (instant_list is not None)), ( + "Either string must be not None or instant_list must be not" + ) if _inner is not None: self._inner = as_tsequence(_inner) elif string is not None: self._inner = as_tsequence(self.__class__._parse_function(string)) else: self._instants = [ - ( - x._inner - if isinstance(x, self.ComponentClass) - else self.__class__._parse_function(x) - ) + (x._inner if isinstance(x, self.ComponentClass) else self.__class__._parse_function(x)) for x in instant_list ] count = len(self._instants) @@ -62,8 +58,8 @@ def __init__( @classmethod def from_instants( - cls: Type[Self], - instant_list: Optional[List[Union[str, Any]]], + cls: type[Self], + instant_list: list[str | Any] | None, lower_inc: bool = True, upper_inc: bool = False, interpolation: TInterpolation = TInterpolation.LINEAR, diff --git a/pymeos/temporal/tsequenceset.py b/pymeos/temporal/tsequenceset.py index b9213130..0e14de63 100644 --- a/pymeos/temporal/tsequenceset.py +++ b/pymeos/temporal/tsequenceset.py @@ -1,7 +1,7 @@ from __future__ import annotations from abc import ABC -from typing import Optional, List, Union, Any, TypeVar, Type, TYPE_CHECKING +from typing import TYPE_CHECKING, Any, TypeVar from pymeos_cffi import * @@ -28,26 +28,22 @@ class TSequenceSet(Temporal[TBase, TG, TI, TS, TSS], ABC): # ------------------------- Constructors ---------------------------------- def __init__( self, - string: Optional[str] = None, + string: str | None = None, *, - sequence_list: Optional[List[Union[str, Any]]] = None, + sequence_list: list[str | Any] | None = None, normalize: bool = True, _inner=None, ): - assert (_inner is not None) or ( - (string is not None) != (sequence_list is not None) - ), "Either string must be not None or sequence_list must be not" + assert (_inner is not None) or ((string is not None) != (sequence_list is not None)), ( + "Either string must be not None or sequence_list must be not" + ) if _inner is not None: self._inner = as_tsequenceset(_inner) elif string is not None: self._inner = as_tsequenceset(self.__class__._parse_function(string)) else: sequences = [ - ( - x._inner - if isinstance(x, self.ComponentClass) - else self.__class__._parse_function(x) - ) + (x._inner if isinstance(x, self.ComponentClass) else self.__class__._parse_function(x)) for x in sequence_list ] count = len(sequences) @@ -55,8 +51,8 @@ def __init__( @classmethod def from_sequences( - cls: Type[Self], - sequence_list: Optional[List[Union[str, Any]]] = None, + cls: type[Self], + sequence_list: list[str | Any] | None = None, normalize: bool = True, ) -> Self: """ @@ -96,7 +92,7 @@ def sequence_n(self, n) -> TS: """ return self.ComponentClass(_inner=temporal_sequence_n(self._inner, n + 1)) - def sequences(self) -> List[TS]: + def sequences(self) -> list[TS]: """ Returns the list of sequences in ``self``. """ @@ -111,9 +107,7 @@ def to_dataframe(self) -> pd.DataFrame: pd = import_pandas() sequences = self.sequences() data = { - "sequence": [ - i for i, seq in enumerate(sequences) for _ in range(seq.num_instants()) - ], + "sequence": [i for i, seq in enumerate(sequences) for _ in range(seq.num_instants())], "time": [t for seq in sequences for t in seq.timestamps()], "value": [v for seq in sequences for v in seq.values()], } diff --git a/pyproject.toml b/pyproject.toml index d0b8aaa2..066b9e79 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -19,10 +19,10 @@ classifiers = [ 'Programming Language :: C', 'Programming Language :: Python', 'Programming Language :: Python :: 3', - 'Programming Language :: Python :: 3.8', - 'Programming Language :: Python :: 3.9', 'Programming Language :: Python :: 3.10', 'Programming Language :: Python :: 3.11', + 'Programming Language :: Python :: 3.12', + 'Programming Language :: Python :: 3.13', 'Programming Language :: Python :: 3 :: Only', 'Programming Language :: Python :: Implementation :: CPython', 'Operating System :: POSIX', @@ -31,9 +31,9 @@ classifiers = [ readme = 'README.md' license = { file = 'LICENSE' } -requires-python = '>=3.8' +requires-python = '>=3.10' dependencies = [ - 'pymeos-cffi >=1.1.0, <2', + 'pymeos-cffi >=1.3.0, <2', 'python-dateutil', 'shapely>=2.0.0', ] diff --git a/ruff.toml b/ruff.toml new file mode 100644 index 00000000..b1b90e80 --- /dev/null +++ b/ruff.toml @@ -0,0 +1,35 @@ +line-length = 120 +indent-width = 4 + +target-version = "py310" + +[format] +quote-style = "double" +indent-style = "space" +line-ending = "auto" + +[lint] +select = [ + # pycodestyle + "E", "W", + # Pyflakes + "F", + # pyupgrade + "UP", + # flake8-bugbear + "B", + # flake8-simplify + "SIM", + # isort + "I", +] +ignore = [ + "F405", "F403", # Allow star imports + "SIM108", # Don't turn if-else assignment to ternary + "SIM116", # Don't simplify long if-else chains + "E501", # Allow long lines for the moment + "E731", # Allow assigning lambda expressions + "UP038", # Alow instance checks with tuples instead of unions +] +[lint.per-file-ignores] +"docs/conf.py" = ["E402"] \ No newline at end of file diff --git a/tests/boxes/stbox_test.py b/tests/boxes/stbox_test.py index cdc109f3..bcc676d9 100644 --- a/tests/boxes/stbox_test.py +++ b/tests/boxes/stbox_test.py @@ -1,25 +1,23 @@ +import math from copy import copy -from datetime import datetime, timezone, timedelta -from shapely import Point, LineString, Polygon -import shapely.geometry +from datetime import datetime, timedelta, timezone import pytest -import math +import shapely.geometry +from shapely import LineString, Point, Polygon from pymeos import ( STBox, - TInterpolation, - TsTzSet, - TsTzSpan, - TsTzSpanSet, - TGeomPointInst, - TGeomPointSeq, - TGeomPointSeqSet, TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, + TGeomPointInst, + TGeomPointSeq, + TGeomPointSeqSet, + TsTzSet, + TsTzSpan, + TsTzSpanSet, ) - from tests.conftest import TestPyMEOS @@ -352,53 +350,25 @@ def test_from_stbox_expand_space_constructor(self, stbox, expected): ], ), ( - STBox( - "STBOX XT(((1,1),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), + STBox("STBOX XT(((1,1),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), [ - STBox( - "STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX XT(((2,1),(3,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX XT(((1,2),(2,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX XT(((2,2),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), + STBox("STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX XT(((2,1),(3,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX XT(((1,2),(2,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX XT(((2,2),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), ], ), ( - STBox( - "STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), + STBox("STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), [ - STBox( - "STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((2,1,1),(3,2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((1,2,1),(2,3,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((2,2,1),(3,3,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((1,1,2),(2,2,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((2,1,2),(3,2,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((1,2,2),(2,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), - STBox( - "STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])" - ), + STBox("STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((2,1,1),(3,2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((1,2,1),(2,3,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((2,2,1),(3,3,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((1,1,2),(2,2,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((2,1,2),(3,2,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((1,2,2),(2,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), + STBox("STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])"), ], ), ], @@ -790,9 +760,9 @@ def test_scale_time(self, stbox, delta, expected): assert stbox.scale_time(delta) == expected def test_shift_scale_time(self): - assert self.stbt.shift_scale_time( - timedelta(days=4), timedelta(hours=4) - ) == STBox("STBOX T([2019-09-05,2019-09-05 04:00:00])") + assert self.stbt.shift_scale_time(timedelta(days=4), timedelta(hours=4)) == STBox( + "STBOX T([2019-09-05,2019-09-05 04:00:00])" + ) @pytest.mark.parametrize( "stbox, expected", @@ -802,15 +772,11 @@ def test_shift_scale_time(self): STBox("STBOX X((1.12,1.12),(2.12,2.12))"), ), ( - STBox( - "STBOX Z((1.123456789,1.123456789,1.123456789),(2.123456789,2.123456789,2.123456789))" - ), + STBox("STBOX Z((1.123456789,1.123456789,1.123456789),(2.123456789,2.123456789,2.123456789))"), STBox("STBOX Z((1.12,1.12,1.12),(2.12,2.12,2.12))"), ), ( - STBox( - "STBOX XT(((1.123456789,1.123456789),(2.123456789,2.123456789)),[2019-09-01, 2019-09-02])" - ), + STBox("STBOX XT(((1.123456789,1.123456789),(2.123456789,2.123456789)),[2019-09-01, 2019-09-02])"), STBox("STBOX XT(((1.12,1.12),(2.12,2.12)),[2019-09-01, 2019-09-03])"), ), ( @@ -818,9 +784,7 @@ def test_shift_scale_time(self): "STBOX ZT(((1.123456789,1.123456789,1.123456789),(2.123456789,2.123456789,2.123456789))," "[2019-09-01, 2019-09-02])" ), - STBox( - "STBOX ZT(((1.12,1.12,1.12),(2.12,2.12,2.12)),[2019-09-01, 2019-09-02])" - ), + STBox("STBOX ZT(((1.12,1.12,1.12),(2.12,2.12,2.12)),[2019-09-01, 2019-09-02])"), ), ], ids=["STBox X", "STBox Z", "STBox XT", "STBox ZT"], diff --git a/tests/boxes/tbox_test.py b/tests/boxes/tbox_test.py index 1bc387e6..c25a86e2 100644 --- a/tests/boxes/tbox_test.py +++ b/tests/boxes/tbox_test.py @@ -1,21 +1,21 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone import pytest from pymeos import ( - TBox, - TsTzSet, - TsTzSpan, - TsTzSpanSet, - IntSpan, FloatSpan, - TIntInst, - TIntSeq, - TIntSeqSet, + IntSpan, + TBox, TFloatInst, TFloatSeq, TFloatSeqSet, + TIntInst, + TIntSeq, + TIntSeqSet, + TsTzSet, + TsTzSpan, + TsTzSpanSet, ) from tests.conftest import TestPyMEOS @@ -258,9 +258,7 @@ def test_from_value_time_constructor(self, value, time, expected): "TBOXFLOAT XT([1.5, 2.5),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00))", ), ( - TFloatSeqSet( - "{[1.5@2019-09-01,2.5@2019-09-02),[1.5@2019-09-03,1.5@2019-09-05)}" - ), + TFloatSeqSet("{[1.5@2019-09-01,2.5@2019-09-02),[1.5@2019-09-03,1.5@2019-09-05)}"), "TBOXFLOAT XT([1.5, 2.5),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00))", ), ], @@ -280,17 +278,13 @@ def test_from_tnumber_constructor(self, tnumber, expected): assert isinstance(tb, TBox) assert str(tb) == expected - @pytest.mark.parametrize( - "tbox", [tbfx, tbt, tbfxt], ids=["TBoxFloat X", "TBox T", "TBoxFloat XT"] - ) + @pytest.mark.parametrize("tbox", [tbfx, tbt, tbfxt], ids=["TBoxFloat X", "TBox T", "TBoxFloat XT"]) def test_from_as_constructor(self, tbox): assert tbox == TBox(str(tbox)) assert tbox == tbox.from_wkb(tbox.as_wkb()) assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) - @pytest.mark.parametrize( - "tbox", [tbfx, tbt, tbfxt], ids=["TBoxFloat X", "TBox T", "TBoxFloat XT"] - ) + @pytest.mark.parametrize("tbox", [tbfx, tbt, tbfxt], ids=["TBoxFloat X", "TBox T", "TBoxFloat XT"]) def test_copy_constructor(self, tbox): other = copy(tbox) assert tbox == other @@ -600,18 +594,12 @@ def test_shift_value(self, tbox, delta, expected): ( tbfxt, timedelta(hours=2), - TBox( - "TBOXFLOAT XT([1, 2]," - "[2019-09-01 02:00:00+00, 2019-09-02 02:00:00+00])" - ), + TBox("TBOXFLOAT XT([1, 2],[2019-09-01 02:00:00+00, 2019-09-02 02:00:00+00])"), ), ( tbfxt, timedelta(hours=-2), - TBox( - "TBOXFLOAT XT([1, 2]," - "[2019-08-31 22:00:00+00, 2019-09-01 22:00:00+00])" - ), + TBox("TBOXFLOAT XT([1, 2],[2019-08-31 22:00:00+00, 2019-09-01 22:00:00+00])"), ), ( tbixt, @@ -626,18 +614,12 @@ def test_shift_value(self, tbox, delta, expected): ( tbixt, timedelta(hours=2), - TBox( - "TBOXINT XT([1, 3)," - "[2019-09-01 02:00:00+00, 2019-09-02 02:00:00+00])" - ), + TBox("TBOXINT XT([1, 3),[2019-09-01 02:00:00+00, 2019-09-02 02:00:00+00])"), ), ( tbixt, timedelta(hours=-2), - TBox( - "TBOXINT XT([1, 3)," - "[2019-08-31 22:00:00+00, 2019-09-01 22:00:00+00])" - ), + TBox("TBOXINT XT([1, 3),[2019-08-31 22:00:00+00, 2019-09-01 22:00:00+00])"), ), ], ids=[ @@ -679,32 +661,22 @@ def test_scale_value(self, tbox, delta, expected): ( tbfxt, timedelta(days=4), - TBox( - "TBOXFLOAT XT([1, 2]," - "[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])" - ), + TBox("TBOXFLOAT XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])"), ), ( tbfxt, timedelta(hours=2), - TBox( - "TBOXFLOAT XT([1, 2]," - "[2019-09-01 00:00:00+00, 2019-09-01 02:00:00+00])" - ), + TBox("TBOXFLOAT XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-01 02:00:00+00])"), ), ( tbixt, timedelta(days=4), - TBox( - "TBOXINT XT([1, 3),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])" - ), + TBox("TBOXINT XT([1, 3),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])"), ), ( tbixt, timedelta(hours=2), - TBox( - "TBOXINT XT([1, 3),[2019-09-01 00:00:00+00, 2019-09-01 02:00:00+00])" - ), + TBox("TBOXINT XT([1, 3),[2019-09-01 00:00:00+00, 2019-09-01 02:00:00+00])"), ), ], ids=[ @@ -805,9 +777,7 @@ def test_shift_scale_time(self, tbox, delta, duration, expected): TBox("TBOXFLOAT X([1.12,2.12])"), ), ( - TBox( - "TBOXFLOAT XT([1.123456789,2.123456789],[2019-09-01, 2019-09-02])" - ), + TBox("TBOXFLOAT XT([1.123456789,2.123456789],[2019-09-01, 2019-09-02])"), TBox("TBOXFLOAT XT([1.12,2.12],[2019-09-01, 2019-09-02])"), ), ( diff --git a/tests/collections/number/floatset_test.py b/tests/collections/number/floatset_test.py index af376983..ff58ec0b 100644 --- a/tests/collections/number/floatset_test.py +++ b/tests/collections/number/floatset_test.py @@ -1,9 +1,8 @@ from copy import copy -from typing import List import pytest -from pymeos import FloatSet, FloatSpan, FloatSpanSet +from pymeos import FloatSet, FloatSpan from tests.conftest import TestPyMEOS @@ -11,7 +10,7 @@ class TestFloatSet(TestPyMEOS): floatset = FloatSet("{1, 2, 3}") @staticmethod - def assert_intset_equality(floatset: FloatSet, values: List[int]): + def assert_intset_equality(floatset: FloatSet, values: list[int]): assert floatset.num_elements() == len(values) assert floatset.elements() == values diff --git a/tests/collections/number/intset_test.py b/tests/collections/number/intset_test.py index 01d13352..e27520c7 100644 --- a/tests/collections/number/intset_test.py +++ b/tests/collections/number/intset_test.py @@ -1,9 +1,8 @@ from copy import copy -from typing import List import pytest -from pymeos import IntSet, IntSpan, IntSpanSet +from pymeos import IntSet, IntSpan from tests.conftest import TestPyMEOS @@ -11,7 +10,7 @@ class TestIntSet(TestPyMEOS): intset = IntSet("{1, 2, 3}") @staticmethod - def assert_intset_equality(intset: IntSet, values: List[int]): + def assert_intset_equality(intset: IntSet, values: list[int]): assert intset.num_elements() == len(values) assert intset.elements() == values diff --git a/tests/collections/number/intspan_test.py b/tests/collections/number/intspan_test.py index c6706eda..75802538 100644 --- a/tests/collections/number/intspan_test.py +++ b/tests/collections/number/intspan_test.py @@ -3,7 +3,6 @@ import pytest from pymeos import IntSpan, IntSpanSet - from tests.conftest import TestPyMEOS @@ -164,64 +163,44 @@ class TestIntSpanTopologicalPositionFunctions(TestIntSpan): intspan = IntSpan("(1, 20)") intspanset = IntSpanSet("{(1, 20), (31, 41)}") - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_is_adjacent(self, other): self.intspan.is_adjacent(other) - @pytest.mark.parametrize( - "other", [intspan, intspanset], ids=["intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [intspan, intspanset], ids=["intspan", "intspanset"]) def test_is_contained_in(self, other): self.intspan.is_contained_in(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_contains(self, other): self.intspan.contains(other) _ = other in self.intspan - @pytest.mark.parametrize( - "other", [intspan, intspanset], ids=["intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [intspan, intspanset], ids=["intspan", "intspanset"]) def test_overlaps(self, other): self.intspan.overlaps(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_is_same(self, other): self.intspan.is_same(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_is_left(self, other): self.intspan.is_left(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_is_over_or_left(self, other): self.intspan.is_over_or_left(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_is_right(self, other): self.intspan.is_right(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_is_over_or_right(self, other): self.intspan.is_over_or_right(other) - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_distance(self, other): self.intspan.distance(other) @@ -231,23 +210,17 @@ class TestIntSpanSetFunctions(TestIntSpan): intspan = IntSpan("(1, 20)") intspanset = IntSpanSet("{(1, 20), (31, 41)}") - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_intersection(self, other): self.intspan.intersection(other) self.intspan * other - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_union(self, other): self.intspan.union(other) self.intspan + other - @pytest.mark.parametrize( - "other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"] - ) + @pytest.mark.parametrize("other", [value, intspan, intspanset], ids=["value", "intspan", "intspanset"]) def test_minus(self, other): self.intspan.minus(other) self.intspan - other diff --git a/tests/collections/text/textset_test.py b/tests/collections/text/textset_test.py index 1b0d6352..ef375882 100644 --- a/tests/collections/text/textset_test.py +++ b/tests/collections/text/textset_test.py @@ -1,6 +1,4 @@ from copy import copy -from datetime import datetime, timezone, timedelta -from typing import List import pytest @@ -12,7 +10,7 @@ class TestTextSet(TestPyMEOS): tset = TextSet("{A, BB, ccc}") @staticmethod - def assert_textset_equality(tset: TextSet, elements: List[str]): + def assert_textset_equality(tset: TextSet, elements: list[str]): assert tset.num_elements() == len(elements) assert tset.elements() == elements diff --git a/tests/collections/time/dateset_test.py b/tests/collections/time/dateset_test.py index 21caa07e..bd3ea465 100644 --- a/tests/collections/time/dateset_test.py +++ b/tests/collections/time/dateset_test.py @@ -4,9 +4,9 @@ import pytest from pymeos import ( + DateSet, DateSpan, DateSpanSet, - DateSet, ) from tests.conftest import TestPyMEOS @@ -61,11 +61,7 @@ def test_to_span(self): assert self.date_set.to_span() == DateSpan("[2019-09-25, 2019-09-27]") def test_to_spanset(self): - expected = DateSpanSet( - "{[2019-09-25, 2019-09-25], " - "[2019-09-26, 2019-09-26], " - "[2019-09-27, 2019-09-27]}" - ) + expected = DateSpanSet("{[2019-09-25, 2019-09-25], [2019-09-26, 2019-09-26], [2019-09-27, 2019-09-27]}") spanset = self.date_set.to_spanset() @@ -130,33 +126,23 @@ def test_contains(self, other, expected): def test_overlaps(self, other): self.date_set.overlaps(other) - @pytest.mark.parametrize( - "other", [date_value, other_date_set], ids=["date", "dateset"] - ) + @pytest.mark.parametrize("other", [date_value, other_date_set], ids=["date", "dateset"]) def test_is_before(self, other): self.date_set.is_before(other) - @pytest.mark.parametrize( - "other", [date_value, other_date_set], ids=["date", "dateset"] - ) + @pytest.mark.parametrize("other", [date_value, other_date_set], ids=["date", "dateset"]) def test_is_over_or_before(self, other): self.date_set.is_over_or_before(other) - @pytest.mark.parametrize( - "other", [date_value, other_date_set], ids=["date", "dateset"] - ) + @pytest.mark.parametrize("other", [date_value, other_date_set], ids=["date", "dateset"]) def test_is_after(self, other): self.date_set.is_after(other) - @pytest.mark.parametrize( - "other", [date_value, other_date_set], ids=["date", "dateset"] - ) + @pytest.mark.parametrize("other", [date_value, other_date_set], ids=["date", "dateset"]) def test_is_over_or_after(self, other): self.date_set.is_over_or_after(other) - @pytest.mark.parametrize( - "other", [date_value, other_date_set], ids=["date", "dateset"] - ) + @pytest.mark.parametrize("other", [date_value, other_date_set], ids=["date", "dateset"]) def test_distance(self, other): self.date_set.distance(other) @@ -200,7 +186,7 @@ class TestDateSetComparisons(TestDateSet): other = DateSet("{2020-01-02, 2020-03-31}") def test_eq(self): - assert not self.dateset == self.other + assert self.dateset == self.other def test_ne(self): assert self.dateset != self.other diff --git a/tests/collections/time/tstzset_test.py b/tests/collections/time/tstzset_test.py index c9263996..55719eae 100644 --- a/tests/collections/time/tstzset_test.py +++ b/tests/collections/time/tstzset_test.py @@ -1,24 +1,21 @@ from copy import copy -from datetime import datetime, timezone, timedelta -from typing import List +from datetime import datetime, timedelta, timezone import pytest from pymeos import ( + TsTzSet, TsTzSpan, TsTzSpanSet, - TsTzSet, ) from tests.conftest import TestPyMEOS class TestTsTzSet(TestPyMEOS): - ts_set = TsTzSet( - "{2019-09-01 00:00:00+0, 2019-09-02 00:00:00+0, 2019-09-03 00:00:00+0}" - ) + ts_set = TsTzSet("{2019-09-01 00:00:00+0, 2019-09-02 00:00:00+0, 2019-09-03 00:00:00+0}") @staticmethod - def assert_tstzset_equality(ts_set: TsTzSet, timestamps: List[datetime]): + def assert_tstzset_equality(ts_set: TsTzSet, timestamps: list[datetime]): assert ts_set.num_elements() == len(timestamps) assert ts_set.elements() == timestamps @@ -83,10 +80,7 @@ def test_copy_constructor(self): class TestTsTzSetOutputs(TestTsTzSet): def test_str(self): - assert ( - str(self.ts_set) - == '{"2019-09-01 00:00:00+00", "2019-09-02 00:00:00+00", "2019-09-03 00:00:00+00"}' - ) + assert str(self.ts_set) == '{"2019-09-01 00:00:00+00", "2019-09-02 00:00:00+00", "2019-09-03 00:00:00+00"}' def test_repr(self): assert ( @@ -112,28 +106,20 @@ def test_duration(self): assert self.ts_set.duration() == timedelta(days=2) def test_tstzspan(self): - assert self.ts_set.to_span() == TsTzSpan( - "[2019-09-01 00:00:00+00, 2019-09-03 00:00:00+00]" - ) + assert self.ts_set.to_span() == TsTzSpan("[2019-09-01 00:00:00+00, 2019-09-03 00:00:00+00]") def test_num_timestamps(self): assert self.ts_set.num_elements() == 3 assert len(self.ts_set) == 3 def test_start_timestamp(self): - assert self.ts_set.start_element() == datetime( - 2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc - ) + assert self.ts_set.start_element() == datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc) def test_end_timestamp(self): - assert self.ts_set.end_element() == datetime( - 2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc - ) + assert self.ts_set.end_element() == datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc) def test_timestamp_n(self): - assert self.ts_set.element_n(1) == datetime( - 2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc - ) + assert self.ts_set.element_n(1) == datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc) def test_timestamp_n_out_of_range(self): with pytest.raises(IndexError): @@ -158,9 +144,7 @@ class TestTsTzSetPositionFunctions(TestTsTzSet): def test_is_contained_in(self, other, expected): assert self.ts_set.is_contained_in(other) == expected - @pytest.mark.parametrize( - "other", [timestamp, tstzset], ids=["timestamp", "tstzset"] - ) + @pytest.mark.parametrize("other", [timestamp, tstzset], ids=["timestamp", "tstzset"]) def test_contains(self, other): self.ts_set.contains(other) _ = other in self.tstzset @@ -169,33 +153,23 @@ def test_contains(self, other): def test_overlaps(self, other): self.ts_set.overlaps(other) - @pytest.mark.parametrize( - "other", [timestamp, tstzset], ids=["timestamp", "tstzset"] - ) + @pytest.mark.parametrize("other", [timestamp, tstzset], ids=["timestamp", "tstzset"]) def test_is_before(self, other): self.ts_set.is_before(other) - @pytest.mark.parametrize( - "other", [timestamp, tstzset], ids=["timestamp", "tstzset"] - ) + @pytest.mark.parametrize("other", [timestamp, tstzset], ids=["timestamp", "tstzset"]) def test_is_over_or_before(self, other): self.ts_set.is_over_or_before(other) - @pytest.mark.parametrize( - "other", [timestamp, tstzset], ids=["timestamp", "tstzset"] - ) + @pytest.mark.parametrize("other", [timestamp, tstzset], ids=["timestamp", "tstzset"]) def test_is_after(self, other): self.ts_set.is_after(other) - @pytest.mark.parametrize( - "other", [timestamp, tstzset], ids=["timestamp", "tstzset"] - ) + @pytest.mark.parametrize("other", [timestamp, tstzset], ids=["timestamp", "tstzset"]) def test_is_over_or_after(self, other): self.ts_set.is_over_or_after(other) - @pytest.mark.parametrize( - "other", [timestamp, tstzset], ids=["timestamp", "tstzset"] - ) + @pytest.mark.parametrize("other", [timestamp, tstzset], ids=["timestamp", "tstzset"]) def test_distance(self, other): self.ts_set.distance(other) @@ -260,9 +234,7 @@ def test_ge(self): class TestTsTzSetFunctionsFunctions(TestTsTzSet): - tstzset = TsTzSet( - "{2020-01-01 00:00:00+0, 2020-01-02 00:00:00+0, 2020-01-04 00:00:00+0}" - ) + tstzset = TsTzSet("{2020-01-01 00:00:00+0, 2020-01-02 00:00:00+0, 2020-01-04 00:00:00+0}") @pytest.mark.parametrize( "delta,result", @@ -345,9 +317,7 @@ def test_shift_scale(self): class TestTsTzSetMiscFunctions(TestTsTzSet): - tstzset = TsTzSet( - "{2020-01-01 00:00:00+0, 2020-01-02 00:00:00+0, 2020-01-04 00:00:00+0}" - ) + tstzset = TsTzSet("{2020-01-01 00:00:00+0, 2020-01-02 00:00:00+0, 2020-01-04 00:00:00+0}") def test_hash(self): hash(self.tstzset) diff --git a/tests/collections/time/tstzspan_test.py b/tests/collections/time/tstzspan_test.py index c3fec24f..ec7a3ebf 100644 --- a/tests/collections/time/tstzspan_test.py +++ b/tests/collections/time/tstzspan_test.py @@ -1,16 +1,16 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone import pytest from pymeos import ( - TsTzSpan, - TsTzSpanSet, - TBox, STBox, + TBox, TFloatInst, TFloatSeq, TFloatSeqSet, + TsTzSpan, + TsTzSpanSet, ) from tests.conftest import TestPyMEOS @@ -93,9 +93,7 @@ def test_constructor_bounds(self, input_lower, input_upper, lower, upper): self.assert_tstzspan_equality(tstzspan, lower, upper) def test_constructor_bound_inclusivity_defaults(self): - tstzspan = TsTzSpan( - lower="2019-09-08 00:00:00+0", upper="2019-09-10 00:00:00+0" - ) + tstzspan = TsTzSpan(lower="2019-09-08 00:00:00+0", upper="2019-09-10 00:00:00+0") self.assert_tstzspan_equality(tstzspan, lower_inc=True, upper_inc=False) @pytest.mark.parametrize( @@ -134,10 +132,7 @@ def test_str(self): assert str(self.tstzspan) == "(2019-09-08 00:00:00+00, 2019-09-10 00:00:00+00)" def test_repr(self): - assert ( - repr(self.tstzspan) - == "TsTzSpan((2019-09-08 00:00:00+00, 2019-09-10 00:00:00+00))" - ) + assert repr(self.tstzspan) == "TsTzSpan((2019-09-08 00:00:00+00, 2019-09-10 00:00:00+00))" def test_hexwkb(self): assert self.tstzspan == TsTzSpan.from_hexwkb(self.tstzspan.as_hexwkb()) @@ -160,9 +155,7 @@ def test_lower(self): def test_upper(self): assert self.tstzspan.upper() == datetime(2019, 9, 10, tzinfo=timezone.utc) - assert self.tstzspan2.upper() == datetime( - 2019, 9, 10, 2, 3, tzinfo=timezone.utc - ) + assert self.tstzspan2.upper() == datetime(2019, 9, 10, 2, 3, tzinfo=timezone.utc) def test_lower_inc(self): assert not self.tstzspan.lower_inc() @@ -256,9 +249,7 @@ def test_scale(self, delta, result): self.assert_tstzspan_equality(scaled, *result) def test_shift_scale(self): - shifted_scaled = self.tstzspan.shift_scale( - timedelta(days=4), timedelta(hours=4) - ) + shifted_scaled = self.tstzspan.shift_scale(timedelta(days=4), timedelta(hours=4)) self.assert_tstzspan_equality( shifted_scaled, datetime(2019, 9, 12, 0, tzinfo=timezone.utc), @@ -275,15 +266,9 @@ class TestTsTzSpanTopologicalPositionFunctions(TestTsTzSpan): ) timestamp = datetime(year=2020, month=1, day=1) instant = TFloatInst("1.0@2020-01-01") - discrete_sequence = TFloatSeq( - "{1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31}" - ) - stepwise_sequence = TFloatSeq( - "Interp=Step;(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]" - ) - continuous_sequence = TFloatSeq( - "(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]" - ) + discrete_sequence = TFloatSeq("{1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31}") + stepwise_sequence = TFloatSeq("Interp=Step;(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]") + continuous_sequence = TFloatSeq("(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]") sequence_set = TFloatSeqSet( "{(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31], " "(1.0@2021-01-01, 3.0@2021-01-10, 10.0@2021-01-20, 0.0@2021-01-31]}" diff --git a/tests/collections/time/tstzspanset_test.py b/tests/collections/time/tstzspanset_test.py index 777ce227..b129b455 100644 --- a/tests/collections/time/tstzspanset_test.py +++ b/tests/collections/time/tstzspanset_test.py @@ -1,18 +1,17 @@ from copy import copy -from datetime import datetime, timezone, timedelta -from typing import List +from datetime import datetime, timedelta, timezone import pytest from pymeos import ( - TsTzSpan, - TsTzSet, - TsTzSpanSet, + STBox, + TBox, TFloatInst, TFloatSeq, - STBox, TFloatSeqSet, - TBox, + TsTzSet, + TsTzSpan, + TsTzSpanSet, ) from tests.conftest import TestPyMEOS @@ -21,9 +20,7 @@ class TestTsTzSpanSet(TestPyMEOS): tstzspanset = TsTzSpanSet("{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-04]}") @staticmethod - def assert_tstzspanset_equality( - tstzspanset: TsTzSpanSet, tstzspans: List[TsTzSpan] - ): + def assert_tstzspanset_equality(tstzspanset: TsTzSpanSet, tstzspans: list[TsTzSpan]): assert tstzspanset.num_spans() == len(tstzspans) assert tstzspanset.spans() == tstzspans @@ -67,15 +64,13 @@ def test_copy_constructor(self): class TestTsTzSpanSetOutputs(TestTsTzSpanSet): def test_str(self): assert ( - str(self.tstzspanset) - == "{[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00], " + str(self.tstzspanset) == "{[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00], " "[2019-09-03 00:00:00+00, 2019-09-04 00:00:00+00]}" ) def test_repr(self): assert ( - repr(self.tstzspanset) - == "TsTzSpanSet({[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00], " + repr(self.tstzspanset) == "TsTzSpanSet({[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00], " "[2019-09-03 00:00:00+00, 2019-09-04 00:00:00+00]})" ) @@ -100,28 +95,16 @@ def test_num_timestamps(self): assert self.tstzspanset2.num_timestamps() == 3 def test_start_timestamp(self): - assert self.tstzspanset.start_timestamp() == datetime( - 2019, 9, 1, tzinfo=timezone.utc - ) + assert self.tstzspanset.start_timestamp() == datetime(2019, 9, 1, tzinfo=timezone.utc) def test_end_timestamp(self): - assert self.tstzspanset.end_timestamp() == datetime( - 2019, 9, 4, tzinfo=timezone.utc - ) + assert self.tstzspanset.end_timestamp() == datetime(2019, 9, 4, tzinfo=timezone.utc) def test_timestamp_n(self): - assert self.tstzspanset.timestamp_n(0) == datetime( - 2019, 9, 1, tzinfo=timezone.utc - ) - assert self.tstzspanset.timestamp_n(1) == datetime( - 2019, 9, 2, tzinfo=timezone.utc - ) - assert self.tstzspanset.timestamp_n(2) == datetime( - 2019, 9, 3, tzinfo=timezone.utc - ) - assert self.tstzspanset.timestamp_n(3) == datetime( - 2019, 9, 4, tzinfo=timezone.utc - ) + assert self.tstzspanset.timestamp_n(0) == datetime(2019, 9, 1, tzinfo=timezone.utc) + assert self.tstzspanset.timestamp_n(1) == datetime(2019, 9, 2, tzinfo=timezone.utc) + assert self.tstzspanset.timestamp_n(2) == datetime(2019, 9, 3, tzinfo=timezone.utc) + assert self.tstzspanset.timestamp_n(3) == datetime(2019, 9, 4, tzinfo=timezone.utc) def test_timestamps(self): assert self.tstzspanset.timestamps() == TsTzSet( @@ -220,9 +203,7 @@ def test_scale(self, delta, result): self.assert_tstzspanset_equality(scaled, result) def test_shift_scale(self): - shifted_scaled = self.tstzspanset.shift_scale( - timedelta(days=4), timedelta(hours=6) - ) + shifted_scaled = self.tstzspanset.shift_scale(timedelta(days=4), timedelta(hours=6)) self.assert_tstzspanset_equality( shifted_scaled, [ @@ -239,15 +220,9 @@ class TestTsTzSpanSetTopologicalPositionFunctions(TestTsTzSpanSet): ) timestamp = datetime(year=2020, month=1, day=1) instant = TFloatInst("1.0@2020-01-01") - discrete_sequence = TFloatSeq( - "{1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31}" - ) - stepwise_sequence = TFloatSeq( - "Interp=Step;(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]" - ) - continuous_sequence = TFloatSeq( - "(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]" - ) + discrete_sequence = TFloatSeq("{1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31}") + stepwise_sequence = TFloatSeq("Interp=Step;(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]") + continuous_sequence = TFloatSeq("(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31]") sequence_set = TFloatSeqSet( "{(1.0@2020-01-01, 3.0@2020-01-10, 10.0@2020-01-20, 0.0@2020-01-31], " "(1.0@2021-01-01, 3.0@2021-01-10, 10.0@2021-01-20, 0.0@2021-01-31]}" diff --git a/tests/conftest.py b/tests/conftest.py index c22d110e..f2e4372f 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,4 +1,4 @@ -from pymeos import pymeos_initialize, pymeos_finalize +from pymeos import pymeos_finalize, pymeos_initialize def pytest_configure(config): diff --git a/tests/main/tbool_test.py b/tests/main/tbool_test.py index 4be963aa..92400c62 100644 --- a/tests/main/tbool_test.py +++ b/tests/main/tbool_test.py @@ -1,5 +1,5 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone import pytest @@ -8,10 +8,10 @@ TBoolInst, TBoolSeq, TBoolSeqSet, + TInterpolation, TIntInst, TIntSeq, TIntSeqSet, - TInterpolation, TsTzSet, TsTzSpan, TsTzSpanSet, @@ -27,9 +27,7 @@ class TestTBoolConstructors(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") @pytest.mark.parametrize( "source, type, interpolation", @@ -46,9 +44,7 @@ class TestTBoolConstructors(TestTBool): TInterpolation.STEPWISE, ), ( - TIntSeqSet( - "{[1@2019-09-01, 0@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 0@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), TBoolSeqSet, TInterpolation.STEPWISE, ), @@ -231,9 +227,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): "Mixed Stepwise Normalized", ], ) - def test_instant_list_sequence_constructor( - self, list, interpolation, normalize, expected - ): + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tbs = TBoolSeq( instant_list=list, interpolation=interpolation, @@ -243,9 +237,7 @@ def test_instant_list_sequence_constructor( assert str(tbs) == expected assert tbs.interpolation() == interpolation - tbs2 = TBoolSeq.from_instants( - list, interpolation=interpolation, normalize=normalize, upper_inc=True - ) + tbs2 = TBoolSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) assert str(tbs2) == expected assert tbs2.interpolation() == interpolation @@ -275,9 +267,7 @@ class TestTBoolOutputs(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -465,9 +455,7 @@ class TestTBoolAccessors(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -841,10 +829,8 @@ def test_hash(self, temporal, expected): assert hash(temporal) == expected def test_value_timestamp(self): - assert self.tbi.value() == True - assert self.tbi.timestamp() == datetime( - year=2019, month=9, day=1, tzinfo=timezone.utc - ) + assert self.tbi.value() + assert self.tbi.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) @pytest.mark.parametrize( "temporal, expected", @@ -860,8 +846,7 @@ def test_lower_upper_inc(self, temporal, expected): def test_sequenceset_sequence_functions(self): tbss1 = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02]," - "[True@2019-09-03, True@2019-09-05], [True@2019-09-06]}" + "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05], [True@2019-09-06]}" ) assert tbss1.num_sequences() == 3 assert tbss1.start_sequence() == TBoolSeq("[True@2019-09-01, False@2019-09-02]") @@ -878,9 +863,7 @@ class TestTBoolTransformations(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -993,16 +976,12 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tbss, timedelta(days=4), - TBoolSeqSet( - "{[True@2019-09-05, False@2019-09-06],[True@2019-09-07, True@2019-09-09]}" - ), + TBoolSeqSet("{[True@2019-09-05, False@2019-09-06],[True@2019-09-07, True@2019-09-09]}"), ), ( tbss, timedelta(days=-4), - TBoolSeqSet( - "{[True@2019-08-28, False@2019-08-29],[True@2019-08-30, True@2019-09-01]}" - ), + TBoolSeqSet("{[True@2019-08-28, False@2019-08-29],[True@2019-08-30, True@2019-09-01]}"), ), ( tbss, @@ -1063,9 +1042,7 @@ def test_shift_time(self, tbool, delta, expected): ( tbss, timedelta(days=4), - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ( tbss, @@ -1091,15 +1068,13 @@ def test_scale_time(self, tbool, delta, expected): assert tbool.scale_time(delta) == expected def test_shift_scale_time(self): - assert self.tbss.shift_scale_time( - timedelta(days=4), timedelta(hours=2) - ) == TBoolSeqSet( + assert self.tbss.shift_scale_time(timedelta(days=4), timedelta(hours=2)) == TBoolSeqSet( "{[True@2019-09-05 00:00:00, False@2019-09-05 00:30:00]," "[True@2019-09-05 01:00:00, True@2019-09-05 02:00:00]}" ) @pytest.mark.parametrize( - "tint, delta, expected", + "original, delta, expected", [ (tbi, timedelta(days=4), TBoolInst("True@2019-09-01")), (tbi, timedelta(hours=12), TBoolInst("True@2019-09-01")), @@ -1113,9 +1088,7 @@ def test_shift_scale_time(self): ( tbs, timedelta(hours=12), - TBoolSeq( - "[True@2019-09-01, True@2019-09-01 12:00:00, False@2019-09-02]" - ), + TBoolSeq("[True@2019-09-01, True@2019-09-01 12:00:00, False@2019-09-02]"), ), (tbss, timedelta(days=4), TBoolSeq("{True@2019-09-01,True@2019-09-05}")), ( @@ -1138,17 +1111,15 @@ def test_shift_scale_time(self): "Sequence Set hours", ], ) - def test_temporal_sample(self, tint, delta, expected): - assert tint.temporal_sample(delta, "2019-09-01") == expected + def test_temporal_sample(self, original, delta, expected): + assert original.temporal_sample(delta, "2019-09-01") == expected class TestTBoolModifications(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") @pytest.mark.parametrize( "temporal, sequence, expected", @@ -1193,9 +1164,7 @@ def test_insert(self, temporal, sequence, expected): ( tbs, TBoolInst("False@2019-09-01"), - TBoolSeqSet( - "{[False@2019-09-01], (True@2019-09-01, False@2019-09-02]}" - ), + TBoolSeqSet("{[False@2019-09-01], (True@2019-09-01, False@2019-09-02]}"), ), ( tbss, @@ -1228,9 +1197,7 @@ def test_update(self, temporal, instant, expected): ( tbss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), - TBoolSeqSet( - "{(True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{(True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=[ @@ -1265,9 +1232,7 @@ def test_delete(self, temporal, time, expected): ( tbss, TBoolInst("True@2019-09-06"), - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-06]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1306,9 +1271,7 @@ class TestTBoolManipulationFunctions(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") compared = TBoolSeq("[False@2019-09-01, True@2019-09-02, True@2019-09-03]") @pytest.mark.parametrize( @@ -1320,9 +1283,7 @@ class TestTBoolManipulationFunctions(TestTBool): ( tbss, timedelta(days=1), - TBoolSeqSet( - "{[True@2019-09-02, False@2019-09-03],[True@2019-09-04, True@2019-09-06]}" - ), + TBoolSeqSet("{[True@2019-09-02, False@2019-09-03],[True@2019-09-04, True@2019-09-06]}"), ), (tbi, timedelta(days=-1), TBoolInst("True@2019-08-31")), (tbds, timedelta(days=-1), TBoolSeq("{True@2019-08-31, False@2019-09-01}")), @@ -1330,9 +1291,7 @@ class TestTBoolManipulationFunctions(TestTBool): ( tbss, timedelta(days=-1), - TBoolSeqSet( - "{[True@2019-08-31, False@2019-09-01],[True@2019-09-02, True@2019-09-04]}" - ), + TBoolSeqSet("{[True@2019-08-31, False@2019-09-01],[True@2019-09-02, True@2019-09-04]}"), ), ], ids=[ @@ -1358,9 +1317,7 @@ def test_shift_time(self, temporal, shift, expected): ( tbss, timedelta(days=10), - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-03 12:00:00],[True@2019-09-06, True@2019-09-11]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-03 12:00:00],[True@2019-09-06, True@2019-09-11]}"), ), ], ids=[ @@ -1393,9 +1350,7 @@ def test_scale_time(self, temporal, scale, expected): tbss, timedelta(days=1), timedelta(days=10), - TBoolSeqSet( - "{[True@2019-09-02, False@2019-09-04 12:00:00],[True@2019-09-07, True@2019-09-12]}" - ), + TBoolSeqSet("{[True@2019-09-02, False@2019-09-04 12:00:00],[True@2019-09-07, True@2019-09-12]}"), ), (tbi, timedelta(days=-1), timedelta(days=10), TBoolInst("True@2019-08-31")), ( @@ -1414,9 +1369,7 @@ def test_scale_time(self, temporal, scale, expected): tbss, timedelta(days=-1), timedelta(days=10), - TBoolSeqSet( - "{[True@2019-08-31, False@2019-09-02 12:00:00],[True@2019-09-05, True@2019-09-010]}" - ), + TBoolSeqSet("{[True@2019-08-31, False@2019-09-02 12:00:00],[True@2019-09-05, True@2019-09-010]}"), ), ], ids=[ @@ -1438,9 +1391,7 @@ class TestTBoolRestrictors(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") timestamp = datetime(2019, 9, 1) timestamp_set = TsTzSet("{2019-09-01, 2019-09-03}") @@ -1500,16 +1451,12 @@ def test_when_false(self, temporal, expected): ( tbss, tstzspan_set, - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ( tbss, True, - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}"), ), (tbss, False, TBoolSeqSet("{[False@2019-09-02]}")), ], @@ -1551,9 +1498,7 @@ def test_at(self, temporal, restrictor, expected): (tbs, TBoolSeq("[True@2019-09-01, True@2019-09-02)")), ( tbss, - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1598,16 +1543,12 @@ def test_at_min(self, temporal, expected): ( tbss, timestamp, - TBoolSeqSet( - "{(True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{(True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ( tbss, timestamp_set, - TBoolSeqSet( - "{(True@2019-09-01, False@2019-09-02],(True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{(True@2019-09-01, False@2019-09-02],(True@2019-09-03, True@2019-09-05]}"), ), (tbss, tstzspan, TBoolSeqSet("{[True@2019-09-03, True@2019-09-05]}")), (tbss, tstzspan_set, None), @@ -1615,9 +1556,7 @@ def test_at_min(self, temporal, expected): ( tbss, False, - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}"), ), ], ids=[ @@ -1671,9 +1610,7 @@ def test_minus_max(self, temporal, expected): (tbs, TBoolSeq("[True@2019-09-01, True@2019-09-02)")), ( tbss, - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1737,10 +1674,7 @@ def test_minus_min(self, temporal, expected): ], ) def test_at_minus(self, temporal, restrictor): - assert ( - TBool.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TBool.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal", @@ -1754,9 +1688,7 @@ def test_at_minus_min_max(self, temporal): class TestTBoolComparisons(TestTBool): tb = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - other = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + other = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") def test_eq(self): _ = self.tb == self.other @@ -1781,9 +1713,7 @@ class TestTBoolEverAlwaysComparisons(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -1838,9 +1768,7 @@ class TestTBoolTemporalComparisons(TestTBool): tbi = TBoolInst("True@2019-09-01") tbds = TBoolSeq("{True@2019-09-01, False@2019-09-02}") tbs = TBoolSeq("[True@2019-09-01, False@2019-09-02]") - tbss = TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ) + tbss = TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}") compared = TBoolSeq("[False@2019-09-01, True@2019-09-02, True@2019-09-03]") @pytest.mark.parametrize( @@ -1851,9 +1779,7 @@ class TestTBoolTemporalComparisons(TestTBool): (tbs, TBoolSeq("[False@2019-09-01, True@2019-09-02]")), ( tbss, - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], diff --git a/tests/main/tfloat_test.py b/tests/main/tfloat_test.py index 3ac74bde..0f212f65 100644 --- a/tests/main/tfloat_test.py +++ b/tests/main/tfloat_test.py @@ -1,30 +1,30 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone from operator import not_ import pytest from pymeos_cffi import MeosInvalidArgValueError from pymeos import ( + FloatSet, + FloatSpan, + FloatSpanSet, TBoolInst, TBoolSeq, TBoolSeqSet, + TBox, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TInt, + TInterpolation, TIntInst, TIntSeq, TIntSeqSet, - TInterpolation, - TBox, TsTzSet, TsTzSpan, TsTzSpanSet, - FloatSpan, - FloatSpanSet, - FloatSet, ) from tests.conftest import TestPyMEOS @@ -37,13 +37,9 @@ class TestTFloatConstructors(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tfsts = TFloatSeq("Interp=Step;[1.5@2019-09-01, 2.5@2019-09-02]") - tfstss = TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfstss = TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "source, type, interpolation", @@ -56,9 +52,7 @@ class TestTFloatConstructors(TestTFloat): ), (TIntSeq("[1@2019-09-01, 2@2019-09-02]"), TFloatSeq, TInterpolation.LINEAR), ( - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), TFloatSeqSet, TInterpolation.LINEAR, ), @@ -241,9 +235,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): "Mixed Linear Normalized", ], ) - def test_instant_list_sequence_constructor( - self, list, interpolation, normalize, expected - ): + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tfs = TFloatSeq( instant_list=list, interpolation=interpolation, @@ -253,9 +245,7 @@ def test_instant_list_sequence_constructor( assert str(tfs) == expected assert tfs.interpolation() == interpolation - tfs2 = TFloatSeq.from_instants( - list, interpolation=interpolation, normalize=normalize, upper_inc=True - ) + tfs2 = TFloatSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) assert str(tfs2) == expected assert tfs2.interpolation() == interpolation @@ -299,13 +289,9 @@ class TestTFloatOutputs(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tfsts = TFloatSeq("Interp=Step;[1.5@2019-09-01, 2.5@2019-09-02]") - tfstss = TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfstss = TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -537,13 +523,9 @@ class TestTFloatConversions(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tfsts = TFloatSeq("Interp=Step;[1.5@2019-09-01, 2.5@2019-09-02]") - tfstss = TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfstss = TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -568,13 +550,9 @@ class TestTFloatAccessors(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tfsts = TFloatSeq("Interp=Step;[1.5@2019-09-01, 2.5@2019-09-02]") - tfstss = TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfstss = TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -1001,9 +979,7 @@ def test_hash(self, temporal, expected): def test_value_timestamp(self): assert self.tfi.value() == 1.5 - assert self.tfi.timestamp() == datetime( - year=2019, month=9, day=1, tzinfo=timezone.utc - ) + assert self.tfi.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) @pytest.mark.parametrize( "temporal, expected", @@ -1019,10 +995,7 @@ def test_lower_upper_inc(self, temporal, expected): assert temporal.upper_inc() == expected def test_sequenceset_sequence_functions(self): - tfss1 = TFloatSeqSet( - "{[1@2019-09-01, 2@2019-09-02]," - "[1@2019-09-03, 1@2019-09-05], [3@2019-09-06]}" - ) + tfss1 = TFloatSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05], [3@2019-09-06]}") assert tfss1.num_sequences() == 3 assert tfss1.start_sequence() == TFloatSeq("[1@2019-09-01, 2@2019-09-02]") assert tfss1.end_sequence() == TFloatSeq("[3@2019-09-06]") @@ -1065,24 +1038,15 @@ class TestTFloatTransformations(TestTFloat): tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") tfsts = TFloatSeq("Interp=Step;[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) - tfstss = TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") + tfstss = TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tfs_d = TFloatSeq("[1.5@2019-09-01]") tfss_d = TFloatSeqSet("{[1.5@2019-09-01],[2.5@2019-09-03]}") tfs_s = TFloatSeq("[1.5@2019-09-01, 1.5@2019-09-02]") - tfss_s = TFloatSeqSet( - "{[1.5@2019-09-01, 1.5@2019-09-02]," "[2.5@2019-09-03, 2.5@2019-09-05]}" - ) + tfss_s = TFloatSeqSet("{[1.5@2019-09-01, 1.5@2019-09-02],[2.5@2019-09-03, 2.5@2019-09-05]}") tfs_l = TFloatSeq("Interp=Step;[1.5@2019-09-01, 2.5@2019-09-02]") - tfss_l = TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02]," - "[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss_l = TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -1186,10 +1150,7 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tfss_s, TInterpolation.STEPWISE, - TFloatSeqSet( - "Interp=Step;{[1.5@2019-09-01, 1.5@2019-09-02]," - "[2.5@2019-09-03, 2.5@2019-09-05]}" - ), + TFloatSeqSet("Interp=Step;{[1.5@2019-09-01, 1.5@2019-09-02],[2.5@2019-09-03, 2.5@2019-09-05]}"), ), (tfi, TInterpolation.LINEAR, TFloatSeq("[1.5@2019-09-01]")), ( @@ -1205,10 +1166,7 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tfss_l, TInterpolation.LINEAR, - TFloatSeqSet( - "{[1.5@2019-09-01, 1.5@2019-09-02)," - "[2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 1.5@2019-09-02),[2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ], ids=[ @@ -1241,18 +1199,12 @@ def test_set_interpolation(self, temporal, interpolation, expected): ( tfss, 2, - TFloatSeqSet( - "{[3.5@2019-09-01, 4.5@2019-09-02]," - "[3.5@2019-09-03, 3.5@2019-09-05]}" - ), + TFloatSeqSet("{[3.5@2019-09-01, 4.5@2019-09-02],[3.5@2019-09-03, 3.5@2019-09-05]}"), ), ( tfss, -2, - TFloatSeqSet( - "{[-0.5@2019-09-01, 0.5@2019-09-02]," - "[-0.5@2019-09-03, -0.5@2019-09-05]}" - ), + TFloatSeqSet("{[-0.5@2019-09-01, 0.5@2019-09-02],[-0.5@2019-09-03, -0.5@2019-09-05]}"), ), ], ids=[ @@ -1278,10 +1230,7 @@ def test_shift_value(self, tfloat, delta, expected): ( tfss, 4, - TFloatSeqSet( - "{[1.5@2019-09-01, 5.5@2019-09-02]," - "[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 5.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ], ids=[ @@ -1307,19 +1256,13 @@ def test_scale_value(self, tfloat, width, expected): tfss, 2, 3, - TFloatSeqSet( - "{[3.5@2019-09-01, 6.5@2019-09-02]," - "[3.5@2019-09-03, 3.5@2019-09-05]}" - ), + TFloatSeqSet("{[3.5@2019-09-01, 6.5@2019-09-02],[3.5@2019-09-03, 3.5@2019-09-05]}"), ), ( tfss, -2, 3, - TFloatSeqSet( - "{[-0.5@2019-09-01, 2.5@2019-09-02]," - "[-0.5@2019-09-03, -0.5@2019-09-05]}" - ), + TFloatSeqSet("{[-0.5@2019-09-01, 2.5@2019-09-02],[-0.5@2019-09-03, -0.5@2019-09-05]}"), ), ], ids=[ @@ -1370,16 +1313,12 @@ def test_shift_scale_value(self, tfloat, delta, width, expected): ( tfss, timedelta(days=4), - TFloatSeqSet( - "{[1.5@2019-09-05, 2.5@2019-09-06],[1.5@2019-09-07, 1.5@2019-09-09]}" - ), + TFloatSeqSet("{[1.5@2019-09-05, 2.5@2019-09-06],[1.5@2019-09-07, 1.5@2019-09-09]}"), ), ( tfss, timedelta(days=-4), - TFloatSeqSet( - "{[1.5@2019-08-28, 2.5@2019-08-29],[1.5@2019-08-30, 1.5@2019-09-01]}" - ), + TFloatSeqSet("{[1.5@2019-08-28, 2.5@2019-08-29],[1.5@2019-08-30, 1.5@2019-09-01]}"), ), ( tfss, @@ -1440,9 +1379,7 @@ def test_shift_time(self, tfloat, delta, expected): ( tfss, timedelta(days=4), - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ( tfss, @@ -1468,11 +1405,8 @@ def test_scale_time(self, tfloat, delta, expected): assert tfloat.scale_time(delta) == expected def test_shift_scale_time(self): - assert self.tfss.shift_scale_time( - timedelta(days=4), timedelta(hours=2) - ) == TFloatSeqSet( - "{[1.5@2019-09-05 00:00:00, 2.5@2019-09-05 00:30:00]," - "[1.5@2019-09-05 01:00:00, 1.5@2019-09-05 02:00:00]}" + assert self.tfss.shift_scale_time(timedelta(days=4), timedelta(hours=2)) == TFloatSeqSet( + "{[1.5@2019-09-05 00:00:00, 2.5@2019-09-05 00:30:00],[1.5@2019-09-05 01:00:00, 1.5@2019-09-05 02:00:00]}" ) @pytest.mark.parametrize( @@ -1521,23 +1455,20 @@ def test_temporal_sample(self, tfloat, delta, expected): ( tfds, timedelta(hours=12), - TFloatSeq("{1.5@2019-09-01, 2@2019-09-01 12:00:00+00, 2@2019-09-02}"), + TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}"), ), (tfs, timedelta(days=4), TFloatSeq("{[2@2019-08-31]}")), ( tfs, timedelta(hours=12), - TFloatSeq( - "{[1.75@2019-09-01, 2.25@2019-09-01 12:00:00+00, 2.5@2019-09-02]}" - ), + TFloatSeq("{[1.75@2019-09-01, 2.25@2019-09-01 12:00:00+00, 2.5@2019-09-02]}"), ), (tfss, timedelta(days=4), TFloatSeq("{[1.75@2019-08-31, 1.5@2019-09-04]}")), ( tfss, timedelta(hours=12), TFloatSeq( - "{[1.75@2019-09-01, 2.25@2019-09-01 12:00:00, 2.5@2019-09-02]," - "[1.5@2019-09-03, 1.5@2019-09-05]}" + "{[1.75@2019-09-01, 2.25@2019-09-01 12:00:00, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" ), ), ], @@ -1578,7 +1509,7 @@ def test_stops(self, tfloat, delta, expected): [ (TFloatInst("1.123456789@2019-09-01"), TFloatInst("1.12@2019-09-01")), ( - TFloatSeq("{1.123456789@2019-09-01," "2.123456789@2019-09-02}"), + TFloatSeq("{1.123456789@2019-09-01,2.123456789@2019-09-02}"), TFloatSeq("{1.12@2019-09-01, 2.12@2019-09-02}"), ), ( @@ -1590,10 +1521,7 @@ def test_stops(self, tfloat, delta, expected): "{[1.123456789@2019-09-01, 2.123456789@2019-09-02]," "[1.123456789@2019-09-03, 1.123456789@2019-09-05]}" ), - TFloatSeq( - "{[1.12@2019-09-01, 2.12@2019-09-02]," - "[1.12@2019-09-03, 1.12@2019-09-05]}" - ), + TFloatSeq("{[1.12@2019-09-01, 2.12@2019-09-02],[1.12@2019-09-03, 1.12@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1606,9 +1534,7 @@ class TestTFloatModifications(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "temporal, sequence, expected", @@ -1631,9 +1557,7 @@ class TestTFloatModifications(TestTFloat): ( tfss, TFloatSeq("[1.5@2019-09-06]"), - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05],[1.5@2019-09-06]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05],[1.5@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1658,9 +1582,7 @@ def test_insert(self, temporal, sequence, expected): ( tfss, TFloatInst("2.5@2019-09-01"), - TFloatSeqSet( - "{[2.5@2019-09-01], (1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[2.5@2019-09-01], (1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1686,9 +1608,7 @@ def test_update(self, temporal, instant, expected): ( tfss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), - TFloatSeqSet( - "{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ], ids=[ @@ -1723,9 +1643,7 @@ def test_delete(self, temporal, time, expected): ( tfss, TFloatInst("1.5@2019-09-06"), - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-06]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1749,9 +1667,7 @@ def test_append_instant(self, temporal, instant, expected): ( tfss, TFloatSeq("[1.5@2019-09-06]"), - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05],[1.5@2019-09-06]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05],[1.5@2019-09-06]}"), ), ], ids=["Discrete Sequence", "Sequence", "SequenceSet"], @@ -1764,9 +1680,7 @@ class TestTFloatMathematicalOperations(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tfloatarg = TFloatSeq("[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]") @pytest.mark.parametrize( @@ -1796,9 +1710,7 @@ def test_temporal_add_temporal(self, temporal, argument, expected): ( tfss, 1, - TFloatSeqSet( - "{[2.5@2019-09-01, 3.5@2019-09-02],[2.5@2019-09-03, 2.5@2019-09-05]}" - ), + TFloatSeqSet("{[2.5@2019-09-01, 3.5@2019-09-02],[2.5@2019-09-03, 2.5@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1836,9 +1748,7 @@ def test_temporal_sub_temporal(self, temporal, argument, expected): ( tfss, 1, - TFloatSeqSet( - "{[0.5@2019-09-01, 1.5@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}" - ), + TFloatSeqSet("{[0.5@2019-09-01, 1.5@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1857,16 +1767,12 @@ def test_temporal_sub_int_float(self, temporal, argument, expected): ( tfs, tfloatarg, - TFloatSeqSet( - "{[3.75@2019-09-01, 4@2019-09-01 12:00:00+00, 3.75@2019-09-02]}" - ), + TFloatSeqSet("{[3.75@2019-09-01, 4@2019-09-01 12:00:00+00, 3.75@2019-09-02]}"), ), ( tfss, tfloatarg, - TFloatSeqSet( - "{[3.75@2019-09-01, 4@2019-09-01 12:00:00+00, 3.75@2019-09-02], [2.25@2019-09-03]}" - ), + TFloatSeqSet("{[3.75@2019-09-01, 4@2019-09-01 12:00:00+00, 3.75@2019-09-02], [2.25@2019-09-03]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1892,9 +1798,7 @@ def test_temporal_mul_temporal(self, temporal, argument, expected): ( tfss, 2, - TFloatSeqSet( - "{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}" - ), + TFloatSeqSet("{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}"), ), ], ids=[ @@ -1926,16 +1830,12 @@ def test_temporal_mul_int_float(self, temporal, argument, expected): ( tfs, tfloatarg, - TFloatSeqSet( - "{[0.6@2019-09-01, 1@2019-09-01 12:00:00+00, 1.667@2019-09-02]}" - ), + TFloatSeqSet("{[0.6@2019-09-01, 1@2019-09-01 12:00:00+00, 1.667@2019-09-02]}"), ), ( tfss, tfloatarg, - TFloatSeqSet( - "{[0.6@2019-09-01, 1@2019-09-01 12:00:00+00, 1.667@2019-09-02], [1@2019-09-03]}" - ), + TFloatSeqSet("{[0.6@2019-09-01, 1@2019-09-01 12:00:00+00, 1.667@2019-09-02], [1@2019-09-03]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1957,9 +1857,7 @@ def test_temporal_div_temporal(self, temporal, argument, expected): ( tfss, 2, - TFloatSeqSet( - "{[0.75@2019-09-01, 1.25@2019-09-02],[0.75@2019-09-03, 0.75@2019-09-05]}" - ), + TFloatSeqSet("{[0.75@2019-09-01, 1.25@2019-09-02],[0.75@2019-09-03, 0.75@2019-09-05]}"), ), ], ids=[ @@ -1994,9 +1892,7 @@ def test_abs(self, temporal): (tfs, TFloatSeq("Interp=Step;[1@2019-09-01, 1@2019-09-02)")), ( tfss, - TFloatSeqSet( - "Interp=Step;{[1@2019-09-01, 1@2019-09-02),[0@2019-09-03, 0@2019-09-05)}" - ), + TFloatSeqSet("Interp=Step;{[1@2019-09-01, 1@2019-09-02),[0@2019-09-03, 0@2019-09-05)}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2015,9 +1911,7 @@ def test_delta_value(self, temporal, expected): (tfs, TFloatSeq("[0.0262@2019-09-01, 0.0436@2019-09-02]")), ( tfss, - TFloatSeqSet( - "{[0.0262@2019-09-01, 0.0436@2019-09-02],[0.0262@2019-09-03, 0.0262@2019-09-05]}" - ), + TFloatSeqSet("{[0.0262@2019-09-01, 0.0436@2019-09-02],[0.0262@2019-09-03, 0.0262@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2036,12 +1930,10 @@ def test_to_radians_to_degrees(self, temporal): @pytest.mark.parametrize( "temporal, expected", [ - (tfs, TFloatSeq("Interp=Step;[-1@2019-09-01, -1@2019-09-02]")), + (tfs, TFloatSeq("Interp=Step;[1@2019-09-01, 1@2019-09-02]")), ( tfss, - TFloatSeqSet( - "Interp=Step;{[-1@2019-09-01, -1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}" - ), + TFloatSeqSet("Interp=Step;{[1@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), ], ids=["Sequence", "SequenceSet"], @@ -2063,9 +1955,7 @@ class TestTFloatRestrictors(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") timestamp = datetime(2019, 9, 1) timestamp_set = TsTzSet("{2019-09-01, 2019-09-03}") @@ -2093,9 +1983,7 @@ class TestTFloatRestrictors(TestTFloat): ( tfss, tstzspan_set, - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ], ids=[ @@ -2161,9 +2049,7 @@ def test_at_time(self, temporal, restrictor, expected): FloatSpan(lower=2.5, upper=2.5, lower_inc=True, upper_inc=True), ] ), - TFloatSeqSet( - "{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}" - ), + TFloatSeqSet("{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}"), ), (tfs, 1.5, TFloatSeq("[1.5@2019-09-01]")), (tfs, 2.5, TFloatSeq("[2.5@2019-09-02]")), @@ -2185,9 +2071,7 @@ def test_at_time(self, temporal, restrictor, expected): FloatSpan(lower=2.5, upper=2.5, lower_inc=True, upper_inc=True), ] ), - TFloatSeq( - "{[1.5@2019-09-01 00:00:00+00], [2.5@2019-09-02 00:00:00+00]}" - ), + TFloatSeq("{[1.5@2019-09-01 00:00:00+00], [2.5@2019-09-02 00:00:00+00]}"), ), ( tfss, @@ -2198,10 +2082,7 @@ def test_at_time(self, temporal, restrictor, expected): ( tfss, FloatSet(elements=[1.5, 2.5]), - TFloatSeqSet( - "{[1.5@2019-09-01], [2.5@2019-09-02]," - "[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01], [2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ( tfss, @@ -2291,16 +2172,12 @@ def test_at_max(self, temporal, expected): ( tfss, timestamp, - TFloatSeqSet( - "{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ( tfss, timestamp_set, - TFloatSeqSet( - "{(1.5@2019-09-01, 2.5@2019-09-02],(1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{(1.5@2019-09-01, 2.5@2019-09-02],(1.5@2019-09-03, 1.5@2019-09-05]}"), ), (tfss, tstzspan, TFloatSeqSet("{[1.5@2019-09-03, 1.5@2019-09-05]}")), (tfss, tstzspan_set, None), @@ -2367,9 +2244,7 @@ def test_minus_time(self, temporal, restrictor, expected): ( tfss, 2.5, - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}"), ), ( tfs, @@ -2428,9 +2303,7 @@ def test_minus_min(self, temporal, expected): (tfs, TFloatSeq("{[1.5@2019-09-01, 2.5@2019-09-02)}")), ( tfss, - TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02), [1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02), [1.5@2019-09-03, 1.5@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2478,10 +2351,7 @@ def test_minus_max(self, temporal, expected): ], ) def test_at_minus_time(self, temporal, restrictor): - assert ( - TFloat.merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TFloat.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal, restrictor", @@ -2563,10 +2433,7 @@ def test_at_minus_time(self, temporal, restrictor): ], ) def test_at_minus_values(self, temporal, restrictor): - assert ( - TFloat.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TFloat.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal", @@ -2950,9 +2817,7 @@ class TestTFloatSplitOperations(TestTFloat): ( tfss, [ - TFloatSeqSet( - "{[1@2019-09-01, 2@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TFloatSeqSet("{[1@2019-09-01, 2@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), TFloatSeqSet("{[2@2019-09-02]}"), ], ), @@ -3030,17 +2895,12 @@ def test_time_split_n(self, temporal, expected): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_value_time_split(self, temporal, expected): - assert ( - temporal.value_time_split(2.0, timedelta(days=2), 0.0, "2019-09-01") - == expected - ) + assert temporal.value_time_split(2.0, timedelta(days=2), 0.0, "2019-09-01") == expected class TestTFloatComparisons(TestTFloat): tf = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - other = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + other = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") def test_eq(self): _ = self.tf == self.other @@ -3065,9 +2925,7 @@ class TestTFloatEverAlwaysComparisons(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01,2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01,2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01,2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01,2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") @pytest.mark.parametrize( "temporal, argument, expected", @@ -3242,9 +3100,7 @@ class TestTFloatTemporalComparisons(TestTFloat): tfi = TFloatInst("1.5@2019-09-01") tfds = TFloatSeq("{1.5@2019-09-01, 2.5@2019-09-02}") tfs = TFloatSeq("[1.5@2019-09-01, 2.5@2019-09-02]") - tfss = TFloatSeqSet( - "{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ) + tfss = TFloatSeqSet("{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}") tintarg = TIntSeq("[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]") tfloatarg = TFloatSeq("[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]") @@ -3256,8 +3112,7 @@ class TestTFloatTemporalComparisons(TestTFloat): ( tfs, TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-01 12:00:00+00]," - "(False@2019-09-01 12:00:00+00, False@2019-09-02]}" + "{[False@2019-09-01, True@2019-09-01 12:00:00+00],(False@2019-09-01 12:00:00+00, False@2019-09-02]}" ), ), ( @@ -3281,15 +3136,13 @@ def test_temporal_equal_temporal(self, temporal, expected): (tfs, TBoolSeq("[True@2019-09-01, False@2019-09-02]")), ( tfss, - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_temporal_equal_int(self, temporal, expected): - assert temporal.temporal_equal(1) == expected + assert temporal.temporal_equal_1(1) == expected @pytest.mark.parametrize( "temporal, expected", @@ -3312,7 +3165,7 @@ def test_temporal_equal_int(self, temporal, expected): ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) - def test_temporal_equal_int(self, temporal, expected): + def test_temporal_equal_int_2(self, temporal, expected): assert temporal.temporal_equal(2) == expected @pytest.mark.parametrize( @@ -3326,14 +3179,12 @@ def test_temporal_equal_int(self, temporal, expected): ), ( tfss, - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) - def test_temporal_equal_float(self, temporal, expected): + def test_temporal_equal_float_1_5(self, temporal, expected): assert temporal.temporal_equal(1.5) == expected @pytest.mark.parametrize( @@ -3344,14 +3195,12 @@ def test_temporal_equal_float(self, temporal, expected): (tfs, TBoolSeq("[False@2019-09-01, True@2019-09-02]")), ( tfss, - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) - def test_temporal_equal_float(self, temporal, expected): + def test_temporal_equal_float_2_5(self, temporal, expected): assert temporal.temporal_equal(2.5) == expected @pytest.mark.parametrize( @@ -3362,8 +3211,7 @@ def test_temporal_equal_float(self, temporal, expected): ( tfs, TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-01 12:00:00+00]," - "(True@2019-09-01 12:00:00+00, True@2019-09-02]}" + "{[True@2019-09-01, False@2019-09-01 12:00:00+00],(True@2019-09-01 12:00:00+00, True@2019-09-02]}" ), ), ( @@ -3387,14 +3235,12 @@ def test_temporal_not_equal_temporal(self, temporal, expected): (tfs, TBoolSeq("[False@2019-09-01, True@2019-09-02]")), ( tfss, - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) - def test_temporal_not_equal_int(self, temporal, expected): + def test_temporal_not_equal_int_1(self, temporal, expected): assert temporal.temporal_not_equal(1) == expected @pytest.mark.parametrize( @@ -3405,8 +3251,7 @@ def test_temporal_not_equal_int(self, temporal, expected): ( tfs, TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-01 12:00:00]," - "(True@2019-09-01 12:00:00, True@2019-09-02]}" + "{[True@2019-09-01, False@2019-09-01 12:00:00],(True@2019-09-01 12:00:00, True@2019-09-02]}" ), ), ( @@ -3419,5 +3264,5 @@ def test_temporal_not_equal_int(self, temporal, expected): ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) - def test_temporal_not_equal_int(self, temporal, expected): + def test_temporal_not_equal_int_2(self, temporal, expected): assert temporal.temporal_not_equal(2) == expected diff --git a/tests/main/tgeogpoint_test.py b/tests/main/tgeogpoint_test.py index 5e803f9d..4e415c37 100644 --- a/tests/main/tgeogpoint_test.py +++ b/tests/main/tgeogpoint_test.py @@ -1,28 +1,28 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone from operator import not_ import numpy as np import pytest import shapely.geometry from pymeos_cffi import MeosInvalidArgValueError -from shapely import Point, LineString, set_srid +from shapely import LineString, Point, set_srid from pymeos import ( + STBox, TBoolInst, TBoolSeq, TBoolSeqSet, TFloatInst, TFloatSeq, TFloatSeqSet, - TGeomPointInst, - TGeomPointSeq, - TGeomPointSeqSet, TGeogPoint, TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, - STBox, + TGeomPointInst, + TGeomPointSeq, + TGeomPointSeqSet, TInterpolation, TsTzSet, TsTzSpan, @@ -46,8 +46,7 @@ class TestTGeogPointConstructors(TestTGeogPoint): tpds3d = TGeogPointSeq("{Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02}") tps3d = TGeogPointSeq("[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]") tpss3d = TGeogPointSeqSet( - "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]," - "[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" + "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02],[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -80,9 +79,7 @@ class TestTGeogPointConstructors(TestTGeogPoint): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_from_base_constructor(self, source, type, interpolation): - tp = TGeogPoint.from_base_temporal( - shapely.set_srid(shapely.Point(1, 1), 4326), source - ) + tp = TGeogPoint.from_base_temporal(shapely.set_srid(shapely.Point(1, 1), 4326), source) assert isinstance(tp, type) assert tp.interpolation() == interpolation @@ -109,9 +106,7 @@ def test_from_base_constructor(self, source, type, interpolation): ids=["Instant", "Sequence", "Discrete Sequence", "SequenceSet"], ) def test_from_base_time_constructor(self, source, type, interpolation): - tp = TGeogPoint.from_base_time( - shapely.set_srid(shapely.Point(1, 1), 4326), source, interpolation - ) + tp = TGeogPoint.from_base_time(shapely.set_srid(shapely.Point(1, 1), 4326), source, interpolation) assert isinstance(tp, type) assert tp.interpolation() == interpolation @@ -247,9 +242,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): ( [ TGeogPointInst("Point(1 1)@2019-09-01"), - TGeogPointInst( - "Point(1.499885736561676 1.500057091479197)@2019-09-02" - ), + TGeogPointInst("Point(1.499885736561676 1.500057091479197)@2019-09-02"), TGeogPointInst("Point(2 2)@2019-09-03"), ], TInterpolation.LINEAR, @@ -279,9 +272,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): "Mixed Linear Normalized", ], ) - def test_instant_list_sequence_constructor( - self, list, interpolation, normalize, expected - ): + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tps = TGeogPointSeq( instant_list=list, interpolation=interpolation, @@ -291,9 +282,7 @@ def test_instant_list_sequence_constructor( assert str(tps) == expected assert tps.interpolation() == interpolation - tps2 = TGeogPointSeq.from_instants( - list, interpolation=interpolation, normalize=normalize, upper_inc=True - ) + tps2 = TGeogPointSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) assert str(tps2) == expected assert tps2.interpolation() == interpolation @@ -1003,9 +992,7 @@ def test_hash(self, temporal, expected): def test_value_timestamp(self): assert self.tpi.value() == Point(1, 1) - assert self.tpi.timestamp() == datetime( - year=2019, month=9, day=1, tzinfo=timezone.utc - ) + assert self.tpi.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) @pytest.mark.parametrize( "temporal, expected", @@ -1025,13 +1012,9 @@ def test_sequenceset_sequence_functions(self): "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05], [Point(3 3)@2019-09-06]}" ) assert tpss1.num_sequences() == 3 - assert tpss1.start_sequence() == TGeogPointSeq( - "[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]" - ) + assert tpss1.start_sequence() == TGeogPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]") assert tpss1.end_sequence() == TGeogPointSeq("[Point(3 3)@2019-09-06]") - assert tpss1.sequence_n(1) == TGeogPointSeq( - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]" - ) + assert tpss1.sequence_n(1) == TGeogPointSeq("[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]") assert tpss1.sequences() == [ TGeogPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]"), TGeogPointSeq("[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]"), @@ -1050,8 +1033,7 @@ class TestTGeogPointTPointAccessors(TestTGeogPoint): tpds3d = TGeogPointSeq("{Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02}") tps3d = TGeogPointSeq("[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]") tpss3d = TGeogPointSeqSet( - "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]," - "[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" + "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02],[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -1076,8 +1058,7 @@ def test_length(self, temporal, expected): ( tpss, TFloatSeqSet( - "{[0@2019-09-01, 156876.1494@2019-09-02]," - "[156876.1494@2019-09-03, 156876.1494@2019-09-05]}" + "{[0@2019-09-01, 156876.1494@2019-09-02],[156876.1494@2019-09-03, 156876.1494@2019-09-05]}" ), ), ], @@ -1092,10 +1073,7 @@ def test_cumulative_length(self, temporal, expected): (tps, TFloatSeq("Interp=Step;[1.8157@2019-09-01, 1.8157@2019-09-02]")), ( tpss, - TFloatSeqSet( - "Interp=Step;{[1.8157@2019-09-01, 1.8157@2019-09-02]," - "[0@2019-09-03, 0@2019-09-05]}" - ), + TFloatSeqSet("Interp=Step;{[1.8157@2019-09-01, 1.8157@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), ], ids=["Sequence", "SequenceSet"], @@ -1123,9 +1101,7 @@ def test_speed_without_linear_interpolation_throws(self, temporal): (tps, TFloatSeq("[1@2019-09-01, 2@2019-09-02]")), ( tpss, - TFloatSeqSet( - "{[1@2019-09-01, 2@2019-09-02]," "[1@2019-09-03, 1@2019-09-05]}" - ), + TFloatSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1142,9 +1118,7 @@ def test_x_y(self, temporal, expected): (tps3d, TFloatSeq("[1@2019-09-01, 2@2019-09-02]")), ( tpss3d, - TFloatSeqSet( - "{[1@2019-09-01, 2@2019-09-02]," "[1@2019-09-03, 1@2019-09-05]}" - ), + TFloatSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1180,19 +1154,6 @@ def test_x_y_z(self, temporal, expected): def test_has_z(self, temporal, expected): assert temporal.has_z() == expected - @pytest.mark.parametrize( - "temporal, expected", - [ - (tpi3d, True), - (tpds3d, True), - (tps3d, True), - (tpss3d, True), - ], - ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], - ) - def test_has_z(self, temporal, expected): - assert temporal.has_z() == expected - @pytest.mark.parametrize( "temporal, expected", [ @@ -1239,19 +1200,13 @@ def test_is_simple(self, temporal, expected): (tps, TFloatSeq("[0.7846@2019-09-01,0.7846@2019-09-02]")), ( tpss, - TFloatSeqSet( - "{[0.7846@2019-09-01,0.7846@2019-09-02]," - "[0.7846@2019-09-03,0.7846@2019-09-05]}" - ), + TFloatSeqSet("{[0.7846@2019-09-01,0.7846@2019-09-02],[0.7846@2019-09-03,0.7846@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_bearing(self, temporal, expected): - assert ( - temporal.bearing(shapely.set_srid(shapely.Point(3, 3), 4326)).round(4) - == expected - ) + assert temporal.bearing(shapely.set_srid(shapely.Point(3, 3), 4326)).round(4) == expected @pytest.mark.parametrize( "temporal, expected", @@ -1321,15 +1276,11 @@ class TestTGeogPointConversions(TestTGeogPoint): (tpi, TGeomPointInst("SRID=4326;Point(1 1)@2019-09-01")), ( tpds, - TGeomPointSeq( - "SRID=4326;{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}" - ), + TGeomPointSeq("SRID=4326;{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}"), ), ( tps, - TGeomPointSeq( - "SRID=4326;[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]" - ), + TGeomPointSeq("SRID=4326;[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]"), ), ( tpss, @@ -1357,13 +1308,11 @@ class TestTGeogPointTransformations(TestTGeogPoint): tpss_d = TGeogPointSeqSet("{[Point(1 1)@2019-09-01],[Point(2 2)@2019-09-03]}") tps_s = TGeogPointSeq("[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]") tpss_s = TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(2 2)@2019-09-03, Point(2 2)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(2 2)@2019-09-03, Point(2 2)@2019-09-05]}" ) tps_l = TGeogPointSeq("Interp=Step;[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]") tpss_l = TGeogPointSeqSet( - "Interp=Step;{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "Interp=Step;{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -1462,16 +1411,12 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tpds, TInterpolation.STEPWISE, - TGeogPointSeqSet( - "Interp=Step;{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}" - ), + TGeogPointSeqSet("Interp=Step;{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}"), ), ( tps_s, TInterpolation.STEPWISE, - TGeogPointSeq( - "Interp=Step;[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]" - ), + TGeogPointSeq("Interp=Step;[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]"), ), ( tpss_s, @@ -1490,9 +1435,7 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tps_l, TInterpolation.LINEAR, - TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02), [Point(2 2)@2019-09-02]}" - ), + TGeogPointSeqSet("{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02), [Point(2 2)@2019-09-02]}"), ), ( tpss_l, @@ -1545,16 +1488,12 @@ def test_set_interpolation(self, temporal, interpolation, expected): ( tpds, timedelta(hours=2), - TGeogPointSeq( - "{Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00}" - ), + TGeogPointSeq("{Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00}"), ), ( tpds, timedelta(hours=-2), - TGeogPointSeq( - "{Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00}" - ), + TGeogPointSeq("{Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00}"), ), ( tps, @@ -1569,16 +1508,12 @@ def test_set_interpolation(self, temporal, interpolation, expected): ( tps, timedelta(hours=2), - TGeogPointSeq( - "[Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00]" - ), + TGeogPointSeq("[Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00]"), ), ( tps, timedelta(hours=-2), - TGeogPointSeq( - "[Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00]" - ), + TGeogPointSeq("[Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00]"), ), ( tpss, @@ -1646,9 +1581,7 @@ def test_shift_time(self, tpoint, delta, expected): ( tpds, timedelta(hours=2), - TGeogPointSeq( - "{Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00}" - ), + TGeogPointSeq("{Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00}"), ), ( tps, @@ -1658,9 +1591,7 @@ def test_shift_time(self, tpoint, delta, expected): ( tps, timedelta(hours=2), - TGeogPointSeq( - "[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00]" - ), + TGeogPointSeq("[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00]"), ), ( tpss, @@ -1693,9 +1624,7 @@ def test_scale_time(self, tpoint, delta, expected): assert tpoint.scale_time(delta) == expected def test_shift_scale_time(self): - assert self.tpss.shift_scale_time( - timedelta(days=4), timedelta(hours=2) - ) == TGeogPointSeqSet( + assert self.tpss.shift_scale_time(timedelta(days=4), timedelta(hours=2)) == TGeogPointSeqSet( "{[Point(1 1)@2019-09-05 00:00:00, Point(2 2)@2019-09-05 00:30:00]," "[Point(1 1)@2019-09-05 01:00:00, Point(1 1)@2019-09-05 02:00:00]}" ) @@ -1726,8 +1655,7 @@ def test_shift_scale_time(self): tpss, timedelta(hours=12), TGeogPointSeqSet( - "{[POINT(1 1)@2019-09-01, POINT(2 2)@2019-09-02], " - "[POINT(1 1)@2019-09-03, POINT(1 1)@2019-09-05]}" + "{[POINT(1 1)@2019-09-01, POINT(2 2)@2019-09-02], [POINT(1 1)@2019-09-03, POINT(1 1)@2019-09-05]}" ), ), ], @@ -1775,22 +1703,12 @@ def test_stops(self, tpoint, delta, expected): TGeogPointInst("Point(1.12 1.12)@2019-09-01"), ), ( - TGeogPointSeq( - "{Point(1.123456789 1.123456789)@2019-09-01," - "Point(2.123456789 2.123456789)@2019-09-02}" - ), - TGeogPointSeq( - "{Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02}" - ), + TGeogPointSeq("{Point(1.123456789 1.123456789)@2019-09-01,Point(2.123456789 2.123456789)@2019-09-02}"), + TGeogPointSeq("{Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02}"), ), ( - TGeogPointSeq( - "[Point(1.123456789 1.123456789)@2019-09-01," - "Point(2.123456789 2.123456789)@2019-09-02]" - ), - TGeogPointSeq( - "[Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02]" - ), + TGeogPointSeq("[Point(1.123456789 1.123456789)@2019-09-01,Point(2.123456789 2.123456789)@2019-09-02]"), + TGeogPointSeq("[Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02]"), ), ( TGeogPointSeqSet( @@ -1815,29 +1733,15 @@ def test_round(self, temporal, expected): [ ( TGeogPointInst("Point(42.84979 42.38153)@2019-09-01"), - TGeogPointInst("SRID=8426;" "Point(42.84979 42.38153)@2019-09-01"), + TGeogPointInst("SRID=8426;Point(42.84979 42.38153)@2019-09-01"), ), ( - TGeogPointSeq( - "{Point(42.84979 42.38153)@2019-09-01," - "Point(44.31646 41.77403)@2019-09-02}" - ), - TGeogPointSeq( - "SRID=8426;" - "{Point(42.84979 42.38153)@2019-09-01," - "Point(44.31646 41.77403)@2019-09-02}" - ), + TGeogPointSeq("{Point(42.84979 42.38153)@2019-09-01,Point(44.31646 41.77403)@2019-09-02}"), + TGeogPointSeq("SRID=8426;{Point(42.84979 42.38153)@2019-09-01,Point(44.31646 41.77403)@2019-09-02}"), ), ( - TGeogPointSeq( - "[Point(42.84979 42.38153)@2019-09-01," - "Point(44.31646 41.77403)@2019-09-02]" - ), - TGeogPointSeq( - "SRID=8426;" - "[Point(42.84979 42.38153)@2019-09-01," - "Point(44.31646 41.77403)@2019-09-02]" - ), + TGeogPointSeq("[Point(42.84979 42.38153)@2019-09-01,Point(44.31646 41.77403)@2019-09-02]"), + TGeogPointSeq("SRID=8426;[Point(42.84979 42.38153)@2019-09-01,Point(44.31646 41.77403)@2019-09-02]"), ), ( TGeogPointSeqSet( @@ -1884,16 +1788,12 @@ class TestTGeogPointModifications(TestTGeogPoint): ( tpds, TGeogPointSeq("{Point(1 1)@2019-09-03}"), - TGeogPointSeq( - "{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}" - ), + TGeogPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}"), ), ( tps, TGeogPointSeq("[Point(1 1)@2019-09-03]"), - TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]}" - ), + TGeogPointSeqSet("{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]}"), ), ( tpss, @@ -1924,9 +1824,7 @@ def test_insert(self, temporal, sequence, expected): ( tps, TGeogPointInst("Point(2 2)@2019-09-01"), - TGeogPointSeqSet( - "{[Point(2 2)@2019-09-01], (Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}" - ), + TGeogPointSeqSet("{[Point(2 2)@2019-09-01], (Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}"), ), ( tpss, @@ -1986,16 +1884,12 @@ def test_delete(self, temporal, time, expected): ( tpds, TGeogPointInst("Point(1 1)@2019-09-03"), - TGeogPointSeq( - "{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}" - ), + TGeogPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}"), ), ( tps, TGeogPointInst("Point(1 1)@2019-09-03"), - TGeogPointSeq( - "[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]" - ), + TGeogPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]"), ), ( tpss, @@ -2016,16 +1910,12 @@ def test_append_instant(self, temporal, instant, expected): ( tpds, TGeogPointSeq("{Point(1 1)@2019-09-03}"), - TGeogPointSeq( - "{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}" - ), + TGeogPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}"), ), ( tps, TGeogPointSeq("[Point(1 1)@2019-09-03]"), - TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02], [Point(1 1)@2019-09-03]}" - ), + TGeogPointSeqSet("{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02], [Point(1 1)@2019-09-03]}"), ), ( tpss, @@ -2126,16 +2016,13 @@ class TestTGeogPointRestrictors(TestTGeogPoint): tpss, tstzspan_set, TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]," - "[Point(1 1)@2019-09-03,Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03,Point(1 1)@2019-09-05]}" ), ), ( tpss, shapely.set_srid(shapely.Point(1, 1), 4326), - TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ), + TGeogPointSeqSet("{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}"), ), ( tpss, @@ -2341,10 +2228,7 @@ def test_minus(self, temporal, restrictor, expected): ], ) def test_at_minus(self, temporal, restrictor): - assert ( - TGeogPoint.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TGeogPoint.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal", @@ -2352,12 +2236,8 @@ def test_at_minus(self, temporal, restrictor): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_at_minus_min_max(self, temporal): - assert ( - TGeogPoint.from_merge(temporal.at_min(), temporal.minus_min()) == temporal - ) - assert ( - TGeogPoint.from_merge(temporal.at_max(), temporal.minus_max()) == temporal - ) + assert TGeogPoint.from_merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TGeogPoint.from_merge(temporal.at_max(), temporal.minus_max()) == temporal class TestTGeogPointEverSpatialOperations(TestTGeogPoint): @@ -2381,9 +2261,7 @@ class TestTGeogPointEverSpatialOperations(TestTGeogPoint): def test_temporal_ever_withindist_intersects(self, temporal): assert temporal.is_ever_within_distance(Point(1, 1), 1) print("Hey") - assert temporal.is_ever_within_distance( - TGeogPointInst("Point(1 1)@2019-09-01"), 1 - ) + assert temporal.is_ever_within_distance(TGeogPointInst("Point(1 1)@2019-09-01"), 1) print("Hey") assert temporal.ever_intersects(Point(1, 1)) print("Hey") @@ -2391,115 +2269,6 @@ def test_temporal_ever_withindist_intersects(self, temporal): print("Hey") -class TestTGeogPointTemporalSpatialOperations(TestTGeogPoint): - tpi = TGeogPointInst("Point(1 1)@2019-09-01") - tpds = TGeogPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}") - tps = TGeogPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]") - tpss = TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ) - - @pytest.mark.parametrize( - "temporal, expected", - [ - (tpi, TBoolInst("True@2019-09-01")), - (tpds, TBoolSeq("{True@2019-09-01, False@2019-09-02}")), - ( - tps, - TBoolSeqSet( - "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}" - ), - ), - ( - tpss, - TBoolSeqSet( - "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" - ), - ), - ], - ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], - ) - def test_temporal_intersects_disjoint(self, temporal, expected): - assert temporal.intersects(Point(1, 1)) == expected - assert temporal.disjoint(Point(1, 1)) == ~expected - - # Verify that these results are correct wrt lifting the 9DEM definition of touches - @pytest.mark.parametrize( - "temporal, expected", - [ - (tpi, TBoolInst("False@2019-09-01")), - (tpds, TBoolSeq("{False@2019-09-01, False@2019-09-02}")), - (tps, TBoolSeqSet("[False@2019-09-01, False@2019-09-02]")), - ( - tpss, - TBoolSeqSet( - "{[False@2019-09-01, False@2019-09-02]," - "[False@2019-09-03, False@2019-09-05]}" - ), - ), - ], - ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], - ) - def test_temporal_touches(self, temporal, expected): - assert temporal.touches(Point(1, 1)) == expected - - @pytest.mark.parametrize( - "temporal, argument, expected", - [ - (tpi, Point(1, 1), TBoolInst("True@2019-09-01")), - (tpds, Point(1, 1), TBoolSeq("{True@2019-09-01, True@2019-09-02}")), - (tps, Point(1, 1), TBoolSeqSet("{[True@2019-09-01, True@2019-09-02]}")), - ( - tpss, - Point(1, 1), - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" - ), - ), - ( - tpi, - TGeogPointInst("Point(1 1)@2019-09-01"), - TBoolInst("True@2019-09-01"), - ), - ( - tpds, - TGeogPointSeq("{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}"), - TBoolSeq("{True@2019-09-01, False@2019-09-02}"), - ), - ( - tps, - TGeogPointSeq("[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]"), - TBoolSeqSet("{[True@2019-09-01, True@2019-09-02]}"), - ), - ( - tpss, - TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ), - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" - ), - ), - ], - ids=[ - "Instant Geo", - "Discrete Sequence Geo", - "Sequence Geo", - "SequenceSet Geo", - "Instant TPoint", - "Discrete Sequence TPoint", - "Sequence TPoint", - "SequenceSet TPoint", - ], - ) - def test_temporal_withindist(self, temporal, argument, expected): - assert temporal.within_distance(argument, 2) == expected - - class TestTGeogPointDistanceOperations(TestTGeogPoint): tpi = TGeogPointInst("Point(1 1)@2019-09-01") tpds = TGeogPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}") @@ -2517,10 +2286,7 @@ class TestTGeogPointDistanceOperations(TestTGeogPoint): ( tpss, Point(1, 1), - TFloatSeqSet( - "{[0@2019-09-01, 156876.149@2019-09-02]," - "[0@2019-09-03, 0@2019-09-05]}" - ), + TFloatSeqSet("{[0@2019-09-01, 156876.149@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), (tpi, STBox("GEODSTBOX X((1,1),(1,1))"), TFloatInst("0@2019-09-01")), ( @@ -2536,10 +2302,7 @@ class TestTGeogPointDistanceOperations(TestTGeogPoint): ( tpss, STBox("GEODSTBOX X((1,1),(1,1))"), - TFloatSeqSet( - "{[0@2019-09-01, 156876.149@2019-09-02]," - "[0@2019-09-03, 0@2019-09-05]}" - ), + TFloatSeqSet("{[0@2019-09-01, 156876.149@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), (tpi, TGeogPointInst("Point(1 1)@2019-09-01"), TFloatInst("0@2019-09-01")), ( @@ -2555,13 +2318,9 @@ class TestTGeogPointDistanceOperations(TestTGeogPoint): ( tpss, TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ), - TFloatSeqSet( - "{[0@2019-09-01, 156876.149@2019-09-02]," - "[0@2019-09-03, 0@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), + TFloatSeqSet("{[0@2019-09-01, 156876.149@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), ], ids=[ @@ -2596,8 +2355,7 @@ def test_distance(self, temporal, argument, expected): ( tpss, TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), ), ], @@ -2613,9 +2371,7 @@ def test_distance(self, temporal, argument, expected): ], ) def test_nearest_approach_instant(self, temporal, argument): - assert temporal.nearest_approach_instant(argument) == TGeogPointInst( - "Point(1 1)@2019-09-01" - ) + assert temporal.nearest_approach_instant(argument) == TGeogPointInst("Point(1 1)@2019-09-01") @pytest.mark.parametrize( "temporal, argument", @@ -2630,8 +2386,7 @@ def test_nearest_approach_instant(self, temporal, argument): ( tpss, TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), ), ], @@ -2655,8 +2410,7 @@ class TestTGeogPointSimilarityFunctions(TestTGeogPoint): tfds = TGeogPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}") tfs = TGeogPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]") tfss = TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -2740,12 +2494,8 @@ def test_time_split(self, temporal, expected): ( tps, [ - TGeogPointSeq( - "[Point(1 1)@2019-09-01, Point(1.5 1.5)@2019-09-01 12:00:00+00)" - ), - TGeogPointSeq( - "[Point(1.5 1.5)@2019-09-01 12:00:00+00, Point(2 2)@2019-09-02]" - ), + TGeogPointSeq("[Point(1 1)@2019-09-01, Point(1.5 1.5)@2019-09-01 12:00:00+00)"), + TGeogPointSeq("[Point(1.5 1.5)@2019-09-01 12:00:00+00, Point(2 2)@2019-09-02]"), ], ), ( @@ -2861,9 +2611,7 @@ class TestTGeogPointTemporalComparisons(TestTGeogPoint): tpss = TGeogPointSeqSet( "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ) - argument = TGeogPointSeq( - "[Point(2 2)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03]" - ) + argument = TGeogPointSeq("[Point(2 2)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03]") @pytest.mark.parametrize( "temporal, expected", @@ -2873,8 +2621,7 @@ class TestTGeogPointTemporalComparisons(TestTGeogPoint): ( tps, TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-01 12:00:00+00]," - "(False@2019-09-01 12:00:00+00, False@2019-09-02]}" + "{[False@2019-09-01, True@2019-09-01 12:00:00+00],(False@2019-09-01 12:00:00+00, False@2019-09-02]}" ), ), ( @@ -2907,9 +2654,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ( tps, shapely.set_srid(shapely.Point(1, 1), 4326), - TBoolSeqSet( - "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}" - ), + TBoolSeqSet("{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}"), ), ( tpss, @@ -2936,9 +2681,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ( tpss, shapely.set_srid(shapely.Point(2, 2), 4326), - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=[ diff --git a/tests/main/tgeompoint_test.py b/tests/main/tgeompoint_test.py index abb38b6a..d08c6a03 100644 --- a/tests/main/tgeompoint_test.py +++ b/tests/main/tgeompoint_test.py @@ -1,34 +1,32 @@ +import math from copy import copy +from datetime import datetime, timedelta, timezone from operator import not_ -from datetime import datetime, timezone, timedelta -import pytest -import math import numpy as np +import pytest from pymeos_cffi import MeosInvalidArgValueError -from shapely import Point, LineString, Polygon, MultiPoint, GeometryCollection +from shapely import GeometryCollection, LineString, MultiPoint, Point, Polygon from pymeos import ( - TBool, + STBox, TBoolInst, TBoolSeq, TBoolSeqSet, - TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, + TGeogPointInst, + TGeogPointSeq, + TGeogPointSeqSet, TGeomPoint, TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, - TGeogPointInst, - TGeogPointSeq, - TGeogPointSeqSet, TInterpolation, TsTzSet, TsTzSpan, TsTzSpanSet, - STBox, ) from tests.conftest import TestPyMEOS @@ -49,8 +47,7 @@ class TestTGeomPointConstructors(TestTGeomPoint): tpds3d = TGeomPointSeq("{Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02}") tps3d = TGeomPointSeq("[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]") tpss3d = TGeomPointSeqSet( - "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]," - "[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" + "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02],[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -68,9 +65,7 @@ class TestTGeomPointConstructors(TestTGeomPoint): TInterpolation.LINEAR, ), ( - TFloatSeqSet( - "{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), TGeomPointSeqSet, TInterpolation.LINEAR, ), @@ -271,9 +266,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): "Mixed Linear Normalized", ], ) - def test_instant_list_sequence_constructor( - self, list, interpolation, normalize, expected - ): + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tps = TGeomPointSeq( instant_list=list, interpolation=interpolation, @@ -283,9 +276,7 @@ def test_instant_list_sequence_constructor( assert str(tps) == expected assert tps.interpolation() == interpolation - tps2 = TGeomPointSeq.from_instants( - list, interpolation=interpolation, normalize=normalize, upper_inc=True - ) + tps2 = TGeomPointSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) assert str(tps2) == expected assert tps2.interpolation() == interpolation @@ -649,8 +640,7 @@ class TestTGeomPointTemporalAccessors(TestTGeomPoint): tpds3d = TGeomPointSeq("{Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02}") tps3d = TGeomPointSeq("[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]") tpss3d = TGeomPointSeqSet( - "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]," - "[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" + "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02],[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -1032,9 +1022,7 @@ def test_hash(self, temporal, expected): def test_value_timestamp(self): assert self.tpi.value() == Point(1, 1) - assert self.tpi.timestamp() == datetime( - year=2019, month=9, day=1, tzinfo=timezone.utc - ) + assert self.tpi.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) @pytest.mark.parametrize( "temporal, expected", @@ -1054,13 +1042,9 @@ def test_sequenceset_sequence_functions(self): "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05], [Point(3 3)@2019-09-06]}" ) assert tpss1.num_sequences() == 3 - assert tpss1.start_sequence() == TGeomPointSeq( - "[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]" - ) + assert tpss1.start_sequence() == TGeomPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]") assert tpss1.end_sequence() == TGeomPointSeq("[Point(3 3)@2019-09-06]") - assert tpss1.sequence_n(1) == TGeomPointSeq( - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]" - ) + assert tpss1.sequence_n(1) == TGeomPointSeq("[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]") assert tpss1.sequences() == [ TGeomPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]"), TGeomPointSeq("[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]"), @@ -1079,8 +1063,7 @@ class TestTGeomPointTPointAccessors(TestTGeomPoint): tpds3d = TGeomPointSeq("{Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02}") tps3d = TGeomPointSeq("[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]") tpss3d = TGeomPointSeqSet( - "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]," - "[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" + "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02],[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -1120,11 +1103,7 @@ def test_cumulative_length(self, temporal, expected): [ ( tps, - TFloatSeq( - "Interp=Step;[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02]" - ) - / 3600 - / 24, + TFloatSeq("Interp=Step;[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02]") / 3600 / 24, ), ( tpss, @@ -1146,7 +1125,7 @@ def test_speed(self, temporal, expected): [tpi, tpds], ids=["Instant", "Discrete Sequence"], ) - def test_speed(self, temporal): + def test_speed_raises(self, temporal): with pytest.raises(MeosInvalidArgValueError): temporal.speed() @@ -1158,9 +1137,7 @@ def test_speed(self, temporal): (tps, TFloatSeq("[1@2019-09-01, 2@2019-09-02]")), ( tpss, - TFloatSeqSet( - "{[1@2019-09-01, 2@2019-09-02]," "[1@2019-09-03, 1@2019-09-05]}" - ), + TFloatSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1177,9 +1154,7 @@ def test_x_y(self, temporal, expected): (tps3d, TFloatSeq("[1@2019-09-01, 2@2019-09-02]")), ( tpss3d, - TFloatSeqSet( - "{[1@2019-09-01, 2@2019-09-02]," "[1@2019-09-03, 1@2019-09-05]}" - ), + TFloatSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1215,19 +1190,6 @@ def test_x_y_z(self, temporal, expected): def test_has_z(self, temporal, expected): assert temporal.has_z() == expected - @pytest.mark.parametrize( - "temporal, expected", - [ - (tpi3d, True), - (tpds3d, True), - (tps3d, True), - (tpss3d, True), - ], - ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], - ) - def test_has_z(self, temporal, expected): - assert temporal.has_z() == expected - @pytest.mark.parametrize( "temporal, expected", [ @@ -1274,9 +1236,7 @@ def test_is_simple(self, temporal, expected): (tps, TFloatSeq("[45@2019-09-01,45@2019-09-02]")), ( tpss, - TFloatSeqSet( - "{[45@2019-09-01,45@2019-09-02],[45@2019-09-03,45@2019-09-05]}" - ), + TFloatSeqSet("{[45@2019-09-01,45@2019-09-02],[45@2019-09-03,45@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1386,8 +1346,7 @@ class TestTGeomPointConversions(TestTGeomPoint): ( tpss, TGeogPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), ), ], @@ -1422,13 +1381,11 @@ class TestTGeomPointTransformations(TestTGeomPoint): tpss_d = TGeomPointSeqSet("{[Point(1 1)@2019-09-01],[Point(2 2)@2019-09-03]}") tps_s = TGeomPointSeq("[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]") tpss_s = TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(2 2)@2019-09-03, Point(2 2)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(2 2)@2019-09-03, Point(2 2)@2019-09-05]}" ) tps_l = TGeomPointSeq("Interp=Step;[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]") tpss_l = TGeomPointSeqSet( - "Interp=Step;{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "Interp=Step;{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -1527,16 +1484,12 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tpds, TInterpolation.STEPWISE, - TGeomPointSeqSet( - "Interp=Step;{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}" - ), + TGeomPointSeqSet("Interp=Step;{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}"), ), ( tps_s, TInterpolation.STEPWISE, - TGeomPointSeq( - "Interp=Step;[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]" - ), + TGeomPointSeq("Interp=Step;[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]"), ), ( tpss_s, @@ -1555,9 +1508,7 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( tps_l, TInterpolation.LINEAR, - TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02), [Point(2 2)@2019-09-02]}" - ), + TGeomPointSeqSet("{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02), [Point(2 2)@2019-09-02]}"), ), ( tpss_l, @@ -1610,16 +1561,12 @@ def test_set_interpolation(self, temporal, interpolation, expected): ( tpds, timedelta(hours=2), - TGeomPointSeq( - "{Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00}" - ), + TGeomPointSeq("{Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00}"), ), ( tpds, timedelta(hours=-2), - TGeomPointSeq( - "{Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00}" - ), + TGeomPointSeq("{Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00}"), ), ( tps, @@ -1634,16 +1581,12 @@ def test_set_interpolation(self, temporal, interpolation, expected): ( tps, timedelta(hours=2), - TGeomPointSeq( - "[Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00]" - ), + TGeomPointSeq("[Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00]"), ), ( tps, timedelta(hours=-2), - TGeomPointSeq( - "[Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00]" - ), + TGeomPointSeq("[Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00]"), ), ( tpss, @@ -1711,9 +1654,7 @@ def test_shift_time(self, tpoint, delta, expected): ( tpds, timedelta(hours=2), - TGeomPointSeq( - "{Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00}" - ), + TGeomPointSeq("{Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00}"), ), ( tps, @@ -1723,9 +1664,7 @@ def test_shift_time(self, tpoint, delta, expected): ( tps, timedelta(hours=2), - TGeomPointSeq( - "[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00]" - ), + TGeomPointSeq("[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00]"), ), ( tpss, @@ -1758,9 +1697,7 @@ def test_scale_time(self, tpoint, delta, expected): assert tpoint.scale_time(delta) == expected def test_shift_scale_time(self): - assert self.tpss.shift_scale_time( - timedelta(days=4), timedelta(hours=2) - ) == TGeomPointSeqSet( + assert self.tpss.shift_scale_time(timedelta(days=4), timedelta(hours=2)) == TGeomPointSeqSet( "{[Point(1 1)@2019-09-05 00:00:00, Point(2 2)@2019-09-05 00:30:00]," "[Point(1 1)@2019-09-05 01:00:00, Point(1 1)@2019-09-05 02:00:00]}" ) @@ -1840,22 +1777,12 @@ def test_stops(self, tpoint, delta, expected): TGeomPointInst("Point(1.12 1.12)@2019-09-01"), ), ( - TGeomPointSeq( - "{Point(1.123456789 1.123456789)@2019-09-01," - "Point(2.123456789 2.123456789)@2019-09-02}" - ), - TGeomPointSeq( - "{Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02}" - ), + TGeomPointSeq("{Point(1.123456789 1.123456789)@2019-09-01,Point(2.123456789 2.123456789)@2019-09-02}"), + TGeomPointSeq("{Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02}"), ), ( - TGeomPointSeq( - "[Point(1.123456789 1.123456789)@2019-09-01," - "Point(2.123456789 2.123456789)@2019-09-02]" - ), - TGeomPointSeq( - "[Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02]" - ), + TGeomPointSeq("[Point(1.123456789 1.123456789)@2019-09-01,Point(2.123456789 2.123456789)@2019-09-02]"), + TGeomPointSeq("[Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02]"), ), ( TGeomPointSeqSet( @@ -1894,42 +1821,21 @@ def test_round(self, temporal, expected): def test_make_simple(self, temporal, expected): assert temporal.make_simple() == expected - @pytest.mark.parametrize( - "temporal, expected", - [ - (tpi, STBox("STBOX XT(((-1,-1),(3,3)),[2019-09-01, 2019-09-01])")), - (tpds, STBox("STBOX XT(((-1,-1),(4,4)),[2019-09-01, 2019-09-02])")), - (tps, STBox("STBOX XT(((-1,-1),(4,4)),[2019-09-01, 2019-09-02])")), - (tpss, STBox("STBOX XT(((-1,-1),(4,4)),[2019-09-01, 2019-09-05])")), - ], - ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], - ) - def test_expand(self, temporal, expected): - assert temporal.expand(2) == expected - @pytest.mark.parametrize( "temporal, expected", [ ( TGeomPointInst("SRID=4326;Point(2.05455 41.62840)@2019-09-01"), - TGeomPointInst( - "SRID=2062;Point(1077794.3091235077 796037.0089003219)@2019-09-01" - ), + TGeomPointInst("SRID=2062;Point(1077794.3091235077 796037.0089003219)@2019-09-01"), ), ( - TGeomPointSeq( - "SRID=4326;{Point(2.05455 41.62840)@2019-09-01," - "Point(1.63164 41.41622)@2019-09-02}" - ), + TGeomPointSeq("SRID=4326;{Point(2.05455 41.62840)@2019-09-01,Point(1.63164 41.41622)@2019-09-02}"), TGeomPointSeq( "SRID=2062;{Point(1077794.3091235077 796037.0089003219)@2019-09-01,Point(1044050.9767668848 770349.6009306419)@2019-09-02}" ), ), ( - TGeomPointSeq( - "SRID=4326;[Point(2.05455 41.62840)@2019-09-01," - "Point(1.63164 41.41622)@2019-09-02]" - ), + TGeomPointSeq("SRID=4326;[Point(2.05455 41.62840)@2019-09-01,Point(1.63164 41.41622)@2019-09-02]"), TGeomPointSeq( "SRID=2062;[Point(1077794.3091235077 796037.0089003219)@2019-09-01,Point(1044050.9767668848 770349.6009306419)@2019-09-02]" ), @@ -1976,16 +1882,12 @@ class TestTGeomPointModifications(TestTGeomPoint): ( tpds, TGeomPointSeq("{Point(1 1)@2019-09-03}"), - TGeomPointSeq( - "{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}" - ), + TGeomPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}"), ), ( tps, TGeomPointSeq("[Point(1 1)@2019-09-03]"), - TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]}" - ), + TGeomPointSeqSet("{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]}"), ), ( tpss, @@ -2016,9 +1918,7 @@ def test_insert(self, temporal, sequence, expected): ( tps, TGeomPointInst("Point(2 2)@2019-09-01"), - TGeomPointSeqSet( - "{[Point(2 2)@2019-09-01], (Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}" - ), + TGeomPointSeqSet("{[Point(2 2)@2019-09-01], (Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}"), ), ( tpss, @@ -2078,16 +1978,12 @@ def test_delete(self, temporal, time, expected): ( tpds, TGeomPointInst("Point(1 1)@2019-09-03"), - TGeomPointSeq( - "{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}" - ), + TGeomPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}"), ), ( tps, TGeomPointInst("Point(1 1)@2019-09-03"), - TGeomPointSeq( - "[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]" - ), + TGeomPointSeq("[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03]"), ), ( tpss, @@ -2108,16 +2004,12 @@ def test_append_instant(self, temporal, instant, expected): ( tpds, TGeomPointSeq("{Point(1 1)@2019-09-03}"), - TGeomPointSeq( - "{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}" - ), + TGeomPointSeq("{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02, Point(1 1)@2019-09-03}"), ), ( tps, TGeomPointSeq("[Point(1 1)@2019-09-03]"), - TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02], [Point(1 1)@2019-09-03]}" - ), + TGeomPointSeqSet("{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02], [Point(1 1)@2019-09-03]}"), ), ( tpss, @@ -2204,9 +2096,7 @@ class TestTGeomPointRestrictors(TestTGeomPoint): ( tpss, Point(1, 1), - TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ), + TGeomPointSeqSet("{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}"), ), (tpss, Point(2, 2), TGeomPointSeqSet("{[Point(2 2)@2019-09-02]}")), ], @@ -2248,9 +2138,7 @@ def test_at(self, temporal, restrictor, expected): (tps, TGeomPointSeqSet("{[Point(1 1)@2019-09-01]}")), ( tpss, - TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03,Point(1 1)@2019-09-05]}" - ), + TGeomPointSeqSet("{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03,Point(1 1)@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2396,8 +2284,7 @@ def test_minus_min(self, temporal, expected): ( tpss, TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02)," - "[Point(1 1)@2019-09-03,Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02),[Point(1 1)@2019-09-03,Point(1 1)@2019-09-05]}" ), ), ], @@ -2465,10 +2352,7 @@ def test_minus_max(self, temporal, expected): ], ) def test_at_minus(self, temporal, restrictor): - assert ( - TGeomPoint.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TGeomPoint.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal", @@ -2476,12 +2360,8 @@ def test_at_minus(self, temporal, restrictor): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_at_minus_min_max(self, temporal): - assert ( - TGeomPoint.from_merge(temporal.at_min(), temporal.minus_min()) == temporal - ) - assert ( - TGeomPoint.from_merge(temporal.at_max(), temporal.minus_max()) == temporal - ) + assert TGeomPoint.from_merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TGeomPoint.from_merge(temporal.at_max(), temporal.minus_max()) == temporal class TestTGeomPointTopologicalFunctions(TestTGeomPoint): @@ -2682,8 +2562,7 @@ class TestTGeomPointPositionFunctions(TestTGeomPoint): tpds3d = TGeomPointSeq("{Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02}") tps3d = TGeomPointSeq("[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]") tpss3d = TGeomPointSeqSet( - "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02]," - "[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" + "{[Point(1 1 1)@2019-09-01, Point(2 2 2)@2019-09-02],[Point(1 1 1)@2019-09-03, Point(1 1 1)@2019-09-05]}" ) @pytest.mark.parametrize( @@ -2959,23 +2838,12 @@ class TestTGeomPointEverSpatialOperations(TestTGeomPoint): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_temporal_ever_contained_withindist_intersects(self, temporal, expected): - assert ( - temporal.is_ever_contained_in( - Polygon([(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)]) - ) - == expected - ) + assert temporal.is_ever_contained_in(Polygon([(0, 0), (0, 2), (2, 2), (2, 0), (0, 0)])) == expected assert temporal.is_ever_contained_in(STBox("STBOX X((0,0),(2,2))")) == expected assert temporal.is_ever_within_distance(Point(1, 1), 1) == expected - assert ( - temporal.is_ever_within_distance(TGeomPointInst("Point(1 1)@2019-09-01"), 1) - == expected - ) + assert temporal.is_ever_within_distance(TGeomPointInst("Point(1 1)@2019-09-01"), 1) == expected assert temporal.ever_intersects(Point(1, 1)) == expected - assert ( - temporal.ever_intersects(TGeomPointInst("Point(1 1)@2019-09-01")) - == expected - ) + assert temporal.ever_intersects(TGeomPointInst("Point(1 1)@2019-09-01")) == expected # Verify that these results are correct wrt lifting the 9DEM definition of touches @pytest.mark.parametrize( @@ -3003,10 +2871,7 @@ def test_temporal_ever_touches(self, temporal, expected): ) def test_temporal_ever_disjoint(self, temporal, expected): assert temporal.is_ever_disjoint(Point(3, 3)) == expected - assert ( - temporal.is_ever_disjoint(TGeomPointInst("Point(3 3)@2019-09-01")) - == expected - ) + assert temporal.is_ever_disjoint(TGeomPointInst("Point(3 3)@2019-09-01")) == expected class TestTGeomPointTemporalSpatialOperations(TestTGeomPoint): @@ -3024,15 +2889,12 @@ class TestTGeomPointTemporalSpatialOperations(TestTGeomPoint): (tpds, TBoolSeq("{True@2019-09-01, False@2019-09-02}")), ( tps, - TBoolSeqSet( - "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}" - ), + TBoolSeqSet("{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}"), ), ( tpss, TBoolSeqSet( - "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" + "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" ), ), ], @@ -3051,10 +2913,7 @@ def test_temporal_intersects_disjoint(self, temporal, expected): (tps, TBoolSeqSet("[False@2019-09-01, False@2019-09-02]")), ( tpss, - TBoolSeqSet( - "{[False@2019-09-01, False@2019-09-02]," - "[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, False@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -3071,10 +2930,7 @@ def test_temporal_touches(self, temporal, expected): ( tpss, Point(1, 1), - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ( tpi, @@ -3094,13 +2950,9 @@ def test_temporal_touches(self, temporal, expected): ( tpss, TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ), - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=[ @@ -3125,25 +2977,14 @@ def test_temporal_withindist(self, temporal, argument, expected): (tps, TBoolSeqSet("{[True@2019-09-01, True@2019-09-02]}")), ( tpss, - TBoolSeqSet( - "{[True@2019-09-01, True@2019-09-02]," - "[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, True@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_temporal_contained(self, temporal, expected): - assert ( - temporal.is_spatially_contained_in( - Polygon([(0, 0), (0, 3), (3, 3), (3, 0), (0, 0)]) - ) - == expected - ) - assert ( - temporal.is_spatially_contained_in(STBox("STBOX X((0,0),(3,3))")) - == expected - ) + assert temporal.is_spatially_contained_in(Polygon([(0, 0), (0, 3), (3, 3), (3, 0), (0, 0)])) == expected + assert temporal.is_spatially_contained_in(STBox("STBOX X((0,0),(3,3))")) == expected class TestTGeomPointDistanceOperations(TestTGeomPoint): @@ -3163,9 +3004,7 @@ class TestTGeomPointDistanceOperations(TestTGeomPoint): ( tpss, Point(1, 1), - TFloatSeqSet( - "{[0@2019-09-01, 1.414@2019-09-02]," "[0@2019-09-03, 0@2019-09-05]}" - ), + TFloatSeqSet("{[0@2019-09-01, 1.414@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), (tpi, STBox("STBOX X((1,1),(1,1))"), TFloatInst("0@2019-09-01")), ( @@ -3181,9 +3020,7 @@ class TestTGeomPointDistanceOperations(TestTGeomPoint): ( tpss, STBox("STBOX X((1,1),(1,1))"), - TFloatSeqSet( - "{[0@2019-09-01, 1.414@2019-09-02]," "[0@2019-09-03, 0@2019-09-05]}" - ), + TFloatSeqSet("{[0@2019-09-01, 1.414@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), (tpi, TGeomPointInst("Point(1 1)@2019-09-01"), TFloatInst("0@2019-09-01")), ( @@ -3199,12 +3036,9 @@ class TestTGeomPointDistanceOperations(TestTGeomPoint): ( tpss, TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" - ), - TFloatSeqSet( - "{[0@2019-09-01, 1.414@2019-09-02]," "[0@2019-09-03, 0@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), + TFloatSeqSet("{[0@2019-09-01, 1.414@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), ], ids=[ @@ -3239,8 +3073,7 @@ def test_distance(self, temporal, argument, expected): ( tpss, TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), ), ], @@ -3256,9 +3089,7 @@ def test_distance(self, temporal, argument, expected): ], ) def test_nearest_approach_instant(self, temporal, argument): - assert temporal.nearest_approach_instant(argument) == TGeomPointInst( - "Point(1 1)@2019-09-01" - ) + assert temporal.nearest_approach_instant(argument) == TGeomPointInst("Point(1 1)@2019-09-01") @pytest.mark.parametrize( "temporal, argument", @@ -3273,8 +3104,7 @@ def test_nearest_approach_instant(self, temporal, argument): ( tpss, TGeomPointSeqSet( - "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]," - "[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" + "{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ), ), ], @@ -3334,12 +3164,8 @@ def test_time_split(self, temporal, expected): ( tps, [ - TGeomPointSeq( - "[Point(1 1)@2019-09-01, Point(1.5 1.5)@2019-09-01 12:00:00+00)" - ), - TGeomPointSeq( - "[Point(1.5 1.5)@2019-09-01 12:00:00+00, Point(2 2)@2019-09-02]" - ), + TGeomPointSeq("[Point(1 1)@2019-09-01, Point(1.5 1.5)@2019-09-01 12:00:00+00)"), + TGeomPointSeq("[Point(1.5 1.5)@2019-09-01 12:00:00+00, Point(2 2)@2019-09-02]"), ], ), ( @@ -3420,10 +3246,7 @@ def test_space_split(self, temporal, expected): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_space_time_split(self, temporal, expected): - assert ( - temporal.space_time_split(1.0, timedelta(days=2), time_start="2019-09-01") - == expected - ) + assert temporal.space_time_split(1.0, timedelta(days=2), time_start="2019-09-01") == expected class TestTGeomPointComparisons(TestTGeomPoint): @@ -3523,9 +3346,7 @@ class TestTGeomPointTemporalComparisons(TestTGeomPoint): tpss = TGeomPointSeqSet( "{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}" ) - argument = TGeomPointSeq( - "[Point(2 2)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03]" - ) + argument = TGeomPointSeq("[Point(2 2)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03]") @pytest.mark.parametrize( "temporal, expected", @@ -3535,8 +3356,7 @@ class TestTGeomPointTemporalComparisons(TestTGeomPoint): ( tps, TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-01 12:00:00+00]," - "(False@2019-09-01 12:00:00+00, False@2019-09-02]}" + "{[False@2019-09-01, True@2019-09-01 12:00:00+00],(False@2019-09-01 12:00:00+00, False@2019-09-02]}" ), ), ( @@ -3561,9 +3381,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ( tps, Point(1, 1), - TBoolSeqSet( - "{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}" - ), + TBoolSeqSet("{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}"), ), ( tpss, @@ -3578,9 +3396,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ( tpss, Point(2, 2), - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=[ diff --git a/tests/main/tint_test.py b/tests/main/tint_test.py index 03158221..42431b0c 100644 --- a/tests/main/tint_test.py +++ b/tests/main/tint_test.py @@ -1,29 +1,29 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone from operator import not_ import pytest from pymeos import ( + IntSet, + IntSpan, + IntSpanSet, TBoolInst, TBoolSeq, TBoolSeqSet, + TBox, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TInt, + TInterpolation, TIntInst, TIntSeq, TIntSeqSet, - TInterpolation, - TBox, TsTzSet, TsTzSpan, TsTzSpanSet, - IntSpan, - IntSet, - IntSpanSet, ) from tests.conftest import TestPyMEOS @@ -53,9 +53,7 @@ class TestTIntConstructors(TestTInt): TInterpolation.STEPWISE, ), ( - TFloatSeqSet( - "{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}" - ), + TFloatSeqSet("{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}"), TIntSeqSet, TInterpolation.STEPWISE, ), @@ -131,8 +129,7 @@ def test_string_constructor(self, source, type, interpolation, expected): "[1@2019-09-01 00:00:00+00, 2@2019-09-05 00:00:00+00]", ), ( - "{[1@2019-09-01, 1@2019-09-02, 1@2019-09-03, 2@2019-09-05]," - "[1@2019-09-07, 1@2019-09-08, 1@2019-09-09]}", + "{[1@2019-09-01, 1@2019-09-02, 1@2019-09-03, 2@2019-09-05],[1@2019-09-07, 1@2019-09-08, 1@2019-09-09]}", TIntSeqSet, "{[1@2019-09-01 00:00:00+00, 2@2019-09-05 00:00:00+00], " "[1@2019-09-07 00:00:00+00, 1@2019-09-09 00:00:00+00]}", @@ -233,9 +230,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): "Mixed Stepwise Normalized", ], ) - def test_instant_list_sequence_constructor( - self, list, interpolation, normalize, expected - ): + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tis = TIntSeq( instant_list=list, interpolation=interpolation, @@ -245,9 +240,7 @@ def test_instant_list_sequence_constructor( assert str(tis) == expected assert tis.interpolation() == interpolation - tis2 = TIntSeq.from_instants( - list, interpolation=interpolation, normalize=normalize, upper_inc=True - ) + tis2 = TIntSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) assert str(tis2) == expected assert tis2.interpolation() == interpolation @@ -494,9 +487,7 @@ class TestTIntConversions(TestTInt): (tis, TFloatSeq("Interp=Step;[1@2019-09-01,2@2019-09-02]")), ( tiss, - TFloatSeq( - "Interp=Step;{[1@2019-09-01,2@2019-09-02],[1@2019-09-03,1@2019-09-05]}" - ), + TFloatSeq("Interp=Step;{[1@2019-09-01,2@2019-09-02],[1@2019-09-03,1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Step Sequence", "Step Sequence Set"], @@ -899,9 +890,7 @@ def test_hash(self, temporal, expected): def test_value_timestamp(self): assert self.tii.value() == 1 - assert self.tii.timestamp() == datetime( - year=2019, month=9, day=1, tzinfo=timezone.utc - ) + assert self.tii.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) @pytest.mark.parametrize( "temporal, expected", @@ -916,10 +905,7 @@ def test_lower_upper_inc(self, temporal, expected): assert temporal.upper_inc() == expected def test_sequenceset_sequence_functions(self): - tiss1 = TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02]," - "[1@2019-09-03, 1@2019-09-05], [3@2019-09-06]}" - ) + tiss1 = TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05], [3@2019-09-06]}") assert tiss1.num_sequences() == 3 assert tiss1.start_sequence() == TIntSeq("[1@2019-09-01, 2@2019-09-02]") assert tiss1.end_sequence() == TIntSeq("[3@2019-09-06]") @@ -1085,16 +1071,12 @@ def test_set_interpolation(self, temporal, interpolation, expected): ( tiss, 2, - TIntSeqSet( - "{[3@2019-09-01, 4@2019-09-02]," "[3@2019-09-03, 3@2019-09-05]}" - ), + TIntSeqSet("{[3@2019-09-01, 4@2019-09-02],[3@2019-09-03, 3@2019-09-05]}"), ), ( tiss, -2, - TIntSeqSet( - "{[-1@2019-09-01, 0@2019-09-02]," "[-1@2019-09-03, -1@2019-09-05]}" - ), + TIntSeqSet("{[-1@2019-09-01, 0@2019-09-02],[-1@2019-09-03, -1@2019-09-05]}"), ), ], ids=[ @@ -1120,9 +1102,7 @@ def test_shift_value(self, tint, delta, expected): ( tiss, 3, - TIntSeqSet( - "{[1@2019-09-01, 4@2019-09-02], [1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 4@2019-09-02], [1@2019-09-03, 1@2019-09-05]}"), ), ], ids=[ @@ -1148,17 +1128,13 @@ def test_scale_value(self, tint, width, expected): tiss, 2, 3, - TIntSeqSet( - "{[3@2019-09-01, 6@2019-09-02], [3@2019-09-03, 3@2019-09-05]}" - ), + TIntSeqSet("{[3@2019-09-01, 6@2019-09-02], [3@2019-09-03, 3@2019-09-05]}"), ), ( tiss, -2, 3, - TIntSeqSet( - "{[-1@2019-09-01, 2@2019-09-02], [-1@2019-09-03, -1@2019-09-05]}" - ), + TIntSeqSet("{[-1@2019-09-01, 2@2019-09-02], [-1@2019-09-03, -1@2019-09-05]}"), ), ], ids=[ @@ -1209,31 +1185,25 @@ def test_shift_scale_value(self, tint, delta, width, expected): ( tiss, timedelta(days=4), - TIntSeqSet( - "{[1@2019-09-05, 2@2019-09-06],[1@2019-09-07, 1@2019-09-09]}" - ), + TIntSeqSet("{[1@2019-09-05, 2@2019-09-06],[1@2019-09-07, 1@2019-09-09]}"), ), ( tiss, timedelta(days=-4), - TIntSeqSet( - "{[1@2019-08-28, 2@2019-08-29],[1@2019-08-30, 1@2019-09-01]}" - ), + TIntSeqSet("{[1@2019-08-28, 2@2019-08-29],[1@2019-08-30, 1@2019-09-01]}"), ), ( tiss, timedelta(hours=2), TIntSeqSet( - "{[1@2019-09-01 02:00:00, 2@2019-09-02 02:00:00]," - "[1@2019-09-03 02:00:00, 1@2019-09-05 02:00:00]}" + "{[1@2019-09-01 02:00:00, 2@2019-09-02 02:00:00],[1@2019-09-03 02:00:00, 1@2019-09-05 02:00:00]}" ), ), ( tiss, timedelta(hours=-2), TIntSeqSet( - "{[1@2019-08-31 22:00:00, 2@2019-09-01 22:00:00]," - "[1@2019-09-02 22:00:00, 1@2019-09-04 22:00:00]}" + "{[1@2019-08-31 22:00:00, 2@2019-09-01 22:00:00],[1@2019-09-02 22:00:00, 1@2019-09-04 22:00:00]}" ), ), ], @@ -1279,16 +1249,13 @@ def test_shift_time(self, tint, delta, expected): ( tiss, timedelta(days=4), - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ( tiss, timedelta(hours=2), TIntSeqSet( - "{[1@2019-09-01 00:00:00, 2@2019-09-01 00:30:00]," - "[1@2019-09-01 01:00:00, 1@2019-09-01 02:00:00]}" + "{[1@2019-09-01 00:00:00, 2@2019-09-01 00:30:00],[1@2019-09-01 01:00:00, 1@2019-09-01 02:00:00]}" ), ), ], @@ -1307,11 +1274,8 @@ def test_scale_time(self, tint, delta, expected): assert tint.scale_time(delta) == expected def test_shift_scale_time(self): - assert self.tiss.shift_scale_time( - timedelta(days=4), timedelta(hours=2) - ) == TIntSeqSet( - "{[1@2019-09-05 00:00:00, 2@2019-09-05 00:30:00]," - "[1@2019-09-05 01:00:00, 1@2019-09-05 02:00:00]}" + assert self.tiss.shift_scale_time(timedelta(days=4), timedelta(hours=2)) == TIntSeqSet( + "{[1@2019-09-05 00:00:00, 2@2019-09-05 00:30:00],[1@2019-09-05 01:00:00, 1@2019-09-05 02:00:00]}" ) @pytest.mark.parametrize( @@ -1359,9 +1323,7 @@ def test_temporal_sample(self, tint, delta, expected): (tis, TFloatSeq("Interp=Step;[1@2019-09-01, 2@2019-09-02]")), ( tiss, - TFloatSeqSet( - "Interp=Step;{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TFloatSeqSet("Interp=Step;{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1393,9 +1355,7 @@ class TestTIntModifications(TestTInt): ( tiss, TIntSeq("[1@2019-09-06]"), - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05],[1@2019-09-06]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05],[1@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1416,9 +1376,7 @@ def test_insert(self, temporal, sequence, expected): ( tiss, TIntInst("2@2019-09-01"), - TIntSeqSet( - "{[2@2019-09-01], (1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[2@2019-09-01], (1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1444,9 +1402,7 @@ def test_update(self, temporal, instant, expected): ( tiss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), - TIntSeqSet( - "{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=[ @@ -1477,9 +1433,7 @@ def test_delete(self, temporal, time, expected): ( tiss, TIntInst("1@2019-09-06"), - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-06]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1503,9 +1457,7 @@ def test_append_instant(self, temporal, instant, expected): ( tiss, TIntSeq("[1@2019-09-06]"), - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05],[1@2019-09-06]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05],[1@2019-09-06]}"), ), ], ids=["Discrete Sequence", "Sequence", "SequenceSet"], @@ -1548,9 +1500,7 @@ def test_temporal_add_temporal(self, temporal, argument, expected): ( tiss, 1, - TIntSeqSet( - "{[2@2019-09-01, 3@2019-09-02],[2@2019-09-03, 2@2019-09-05]}" - ), + TIntSeqSet("{[2@2019-09-01, 3@2019-09-02],[2@2019-09-03, 2@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1588,9 +1538,7 @@ def test_temporal_sub_temporal(self, temporal, argument, expected): ( tiss, 1, - TIntSeqSet( - "{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}" - ), + TIntSeqSet("{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1636,9 +1584,7 @@ def test_temporal_mul_temporal(self, temporal, argument, expected): ( tiss, 2, - TIntSeqSet( - "{[2@2019-09-01, 4@2019-09-02],[2@2019-09-03, 2@2019-09-05]}" - ), + TIntSeqSet("{[2@2019-09-01, 4@2019-09-02],[2@2019-09-03, 2@2019-09-05]}"), ), ], ids=[ @@ -1693,9 +1639,7 @@ def test_temporal_div_temporal(self, temporal, argument, expected): ( tiss, 2, - TIntSeqSet( - "{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}" - ), + TIntSeqSet("{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}"), ), ], ids=[ @@ -1730,9 +1674,7 @@ def test_abs(self, temporal): (tis, TIntSeq("[1@2019-09-01, 1@2019-09-02)")), ( tiss, - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[0@2019-09-03, 0@2019-09-05)}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[0@2019-09-03, 0@2019-09-05)}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1776,9 +1718,7 @@ class TestTIntRestrictors(TestTInt): ( tiss, tstzspan_set, - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=[ @@ -1863,18 +1803,14 @@ def test_at_time(self, temporal, restrictor, expected): ( tiss, 1, - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), ), (tiss, 2, TIntSeqSet("{[2@2019-09-02]}")), (tiss, IntSet(elements=[1, 2]), tiss), ( tiss, IntSpan(lower=1, upper=1, lower_inc=True, upper_inc=True), - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), ), ( tiss, @@ -1921,9 +1857,7 @@ def test_at_values(self, temporal, restrictor, expected): (tis, TIntSeq("{[1@2019-09-01, 1@2019-09-02)}")), ( tiss, - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1962,16 +1896,12 @@ def test_at_max(self, temporal, expected): ( tiss, timestamp, - TIntSeqSet( - "{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), ), ( tiss, timestamp_set, - TIntSeqSet( - "{(1@2019-09-01, 2@2019-09-02],(1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{(1@2019-09-01, 2@2019-09-02],(1@2019-09-03, 1@2019-09-05]}"), ), (tiss, tstzspan, TIntSeqSet("{[1@2019-09-03, 1@2019-09-05]}")), (tiss, tstzspan_set, None), @@ -2055,9 +1985,7 @@ def test_minus_time(self, temporal, restrictor, expected): ( tiss, 2, - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), ), (tiss, IntSet(elements=[1, 2]), None), ( @@ -2113,9 +2041,7 @@ def test_minus_values(self, temporal, restrictor, expected): (tis, TIntSeq("[1@2019-09-01, 1@2019-09-02)")), ( tiss, - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2248,10 +2174,7 @@ def test_minus_min(self, temporal, expected): ], ) def test_at_minus(self, temporal, restrictor): - assert ( - TInt.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TInt.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal", @@ -2629,9 +2552,7 @@ class TestTIntSplitOperations(TestTInt): ( tiss, [ - TIntSeqSet( - "{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}"), TIntSeq("[2@2019-09-02]"), ], ), @@ -2680,9 +2601,7 @@ def test_time_split(self, temporal, expected): ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], ) def test_value_time_split(self, temporal, expected): - assert ( - temporal.value_time_split(2, timedelta(days=2), 0, "2019-09-01") == expected - ) + assert temporal.value_time_split(2, timedelta(days=2), 0, "2019-09-01") == expected class TestTIntComparisons(TestTInt): @@ -2914,9 +2833,7 @@ def test_temporal_equal_temporal(self, temporal, expected): (tis, TBoolSeq("[True@2019-09-01, False@2019-09-02]")), ( tiss, - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2950,9 +2867,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): (tis, TBoolSeq("[False@2019-09-01, True@2019-09-02]")), ( tiss, - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], diff --git a/tests/main/ttext_test.py b/tests/main/ttext_test.py index c3900997..c575a447 100644 --- a/tests/main/ttext_test.py +++ b/tests/main/ttext_test.py @@ -1,25 +1,23 @@ from copy import copy -from datetime import datetime, timezone, timedelta +from datetime import datetime, timedelta, timezone import pytest from pymeos import ( - TBool, TBoolInst, TBoolSeq, TBoolSeqSet, - TText, - TTextInst, - TTextSeq, - TTextSeqSet, - TInt, + TInterpolation, TIntInst, TIntSeq, TIntSeqSet, - TInterpolation, TsTzSet, TsTzSpan, TsTzSpanSet, + TText, + TTextInst, + TTextSeq, + TTextSeqSet, ) from tests.conftest import TestPyMEOS @@ -32,9 +30,7 @@ class TestTTextConstructors(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "source, type, interpolation", @@ -51,9 +47,7 @@ class TestTTextConstructors(TestTText): TInterpolation.STEPWISE, ), ( - TIntSeqSet( - "{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}" - ), + TIntSeqSet("{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}"), TTextSeqSet, TInterpolation.STEPWISE, ), @@ -234,9 +228,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): "Mixed Stepwise Normalized", ], ) - def test_instant_list_sequence_constructor( - self, list, interpolation, normalize, expected - ): + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tts = TTextSeq( instant_list=list, interpolation=interpolation, @@ -246,9 +238,7 @@ def test_instant_list_sequence_constructor( assert str(tts) == expected assert tts.interpolation() == interpolation - tts2 = TTextSeq.from_instants( - list, interpolation=interpolation, normalize=normalize, upper_inc=True - ) + tts2 = TTextSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) assert str(tts2) == expected assert tts2.interpolation() == interpolation @@ -278,9 +268,7 @@ class TestTTextOutputs(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -480,9 +468,7 @@ class TestTTextAccessors(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -860,9 +846,7 @@ def test_hash(self, temporal, expected): def test_value_timestamp(self): assert self.tti.value() == "AAA" - assert self.tti.timestamp() == datetime( - year=2019, month=9, day=1, tzinfo=timezone.utc - ) + assert self.tti.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) @pytest.mark.parametrize( "temporal, expected", @@ -877,10 +861,7 @@ def test_lower_upper_inc(self, temporal, expected): assert temporal.upper_inc() == expected def test_sequenceset_sequence_functions(self): - ttss1 = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02]," - "[AAA@2019-09-03, AAA@2019-09-05], [CCC@2019-09-06]}" - ) + ttss1 = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05], [CCC@2019-09-06]}") assert ttss1.num_sequences() == 3 assert ttss1.start_sequence() == TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") assert ttss1.end_sequence() == TTextSeq("[CCC@2019-09-06]") @@ -896,9 +877,7 @@ class TestTTextTransformations(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -1011,16 +990,12 @@ def test_to_sequenceset(self, temporal, interpolation, expected): ( ttss, timedelta(days=4), - TTextSeqSet( - "{[AAA@2019-09-05, BBB@2019-09-06],[AAA@2019-09-07, AAA@2019-09-09]}" - ), + TTextSeqSet("{[AAA@2019-09-05, BBB@2019-09-06],[AAA@2019-09-07, AAA@2019-09-09]}"), ), ( ttss, timedelta(days=-4), - TTextSeqSet( - "{[AAA@2019-08-28, BBB@2019-08-29],[AAA@2019-08-30, AAA@2019-09-01]}" - ), + TTextSeqSet("{[AAA@2019-08-28, BBB@2019-08-29],[AAA@2019-08-30, AAA@2019-09-01]}"), ), ( ttss, @@ -1081,9 +1056,7 @@ def test_shift_time(self, ttext, delta, expected): ( ttss, timedelta(days=4), - TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}"), ), ( ttss, @@ -1109,11 +1082,8 @@ def test_scale_time(self, ttext, delta, expected): assert ttext.scale_time(delta) == expected def test_shift_scale(self): - assert self.ttss.shift_scale_time( - timedelta(days=4), timedelta(hours=2) - ) == TTextSeqSet( - "{[AAA@2019-09-05 00:00:00, BBB@2019-09-05 00:30:00]," - "[AAA@2019-09-05 01:00:00, AAA@2019-09-05 02:00:00]}" + assert self.ttss.shift_scale_time(timedelta(days=4), timedelta(hours=2)) == TTextSeqSet( + "{[AAA@2019-09-05 00:00:00, BBB@2019-09-05 00:30:00],[AAA@2019-09-05 01:00:00, AAA@2019-09-05 02:00:00]}" ) @pytest.mark.parametrize( @@ -1158,9 +1128,7 @@ class TestTTextModifications(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, sequence, expected", @@ -1183,9 +1151,7 @@ class TestTTextModifications(TestTText): ( ttss, TTextSeq("[AAA@2019-09-06]"), - TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05],[AAA@2019-09-06]}" - ), + TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05],[AAA@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1210,9 +1176,7 @@ def test_insert(self, temporal, sequence, expected): ( ttss, TTextInst("BBB@2019-09-01"), - TTextSeqSet( - "{[BBB@2019-09-01], (AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[BBB@2019-09-01], (AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1238,9 +1202,7 @@ def test_update(self, temporal, instant, expected): ( ttss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), - TTextSeqSet( - "{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}"), ), ], ids=[ @@ -1275,9 +1237,7 @@ def test_delete(self, temporal, time, expected): ( ttss, TTextInst("AAA@2019-09-06"), - TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-06]}" - ), + TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-06]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1301,9 +1261,7 @@ def test_append_instant(self, temporal, instant, expected): ( ttss, TTextSeq("[AAA@2019-09-06]"), - TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05],[AAA@2019-09-06]}" - ), + TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05],[AAA@2019-09-06]}"), ), ], ids=["Discrete Sequence", "Sequence", "SequenceSet"], @@ -1316,9 +1274,7 @@ class TestTTextTextOperations(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") argument = TTextSeq("[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]") @pytest.mark.parametrize( @@ -1329,9 +1285,7 @@ class TestTTextTextOperations(TestTText): (tts, TTextSeq("[AAABBB@2019-09-01, BBBAAA@2019-09-02]")), ( ttss, - TTextSeqSet( - "{[AAABBB@2019-09-01, BBBAAA@2019-09-02],[AAAAAA@2019-09-03]}" - ), + TTextSeqSet("{[AAABBB@2019-09-01, BBBAAA@2019-09-02],[AAAAAA@2019-09-03]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1348,9 +1302,7 @@ def test_temporal_concat_temporal(self, temporal, expected): (tts, TTextSeq("[AAABBB@2019-09-01, BBBBBB@2019-09-02]")), ( ttss, - TTextSeqSet( - "{[AAABBB@2019-09-01, BBBBBB@2019-09-02],[AAABBB@2019-09-03, AAABBB@2019-09-05]}" - ), + TTextSeqSet("{[AAABBB@2019-09-01, BBBBBB@2019-09-02],[AAABBB@2019-09-03, AAABBB@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1367,9 +1319,7 @@ def test_temporal_concat_text(self, temporal, expected): (tts, TTextSeq("[BBBAAA@2019-09-01, BBBBBB@2019-09-02]")), ( ttss, - TTextSeqSet( - "{[BBBAAA@2019-09-01, BBBBBB@2019-09-02],[BBBAAA@2019-09-03, BBBAAA@2019-09-05]}" - ), + TTextSeqSet("{[BBBAAA@2019-09-01, BBBBBB@2019-09-02],[BBBAAA@2019-09-03, BBBAAA@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1385,9 +1335,7 @@ def test_temporal_radd_text(self, temporal, expected): (tts, TTextSeq("[aaa@2019-09-01, bbb@2019-09-02]")), ( ttss, - TTextSeqSet( - "{[aaa@2019-09-01, bbb@2019-09-02],[aaa@2019-09-03, aaa@2019-09-05]}" - ), + TTextSeqSet("{[aaa@2019-09-01, bbb@2019-09-02],[aaa@2019-09-03, aaa@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1408,9 +1356,7 @@ class TestTTextRestrictors(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") timestamp = datetime(2019, 9, 1) timestamp_set = TsTzSet("{2019-09-01, 2019-09-03}") @@ -1447,16 +1393,12 @@ class TestTTextRestrictors(TestTText): ( ttss, tstzspan_set, - TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}"), ), ( ttss, "AAA", - TTextSeqSet( - "{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}"), ), (ttss, "BBB", TTextSeqSet("{[BBB@2019-09-02]}")), (ttss, ["AAA", "BBB"], ttss), @@ -1516,9 +1458,7 @@ def test_at_max(self, temporal, expected): (tts, TTextSeq("{[AAA@2019-09-01, AAA@2019-09-02)}")), ( ttss, - TTextSeqSet( - "{[AAA@2019-09-01, AAA@2019-09-02), [AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[AAA@2019-09-01, AAA@2019-09-02), [AAA@2019-09-03, AAA@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1553,16 +1493,12 @@ def test_at_min(self, temporal, expected): ( ttss, timestamp, - TTextSeqSet( - "{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}"), ), ( ttss, timestamp_set, - TTextSeqSet( - "{(AAA@2019-09-01, BBB@2019-09-02],(AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{(AAA@2019-09-01, BBB@2019-09-02],(AAA@2019-09-03, AAA@2019-09-05]}"), ), (ttss, tstzspan, TTextSeqSet("{[AAA@2019-09-03, AAA@2019-09-05]}")), (ttss, tstzspan_set, None), @@ -1570,9 +1506,7 @@ def test_at_min(self, temporal, expected): ( ttss, "BBB", - TTextSeqSet( - "{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}"), ), (ttss, ["AAA", "BBB"], None), ], @@ -1634,9 +1568,7 @@ def test_minus_min(self, temporal, expected): (tts, TTextSeq("{[AAA@2019-09-01, AAA@2019-09-02)}")), ( ttss, - TTextSeqSet( - "{[AAA@2019-09-01, AAA@2019-09-02), [AAA@2019-09-03, AAA@2019-09-05]}" - ), + TTextSeqSet("{[AAA@2019-09-01, AAA@2019-09-02), [AAA@2019-09-03, AAA@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -1708,10 +1640,7 @@ def test_minus_max(self, temporal, expected): ], ) def test_at_minus(self, temporal, restrictor): - assert ( - TText.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) - == temporal - ) + assert TText.from_merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal @pytest.mark.parametrize( "temporal", @@ -1727,9 +1656,7 @@ class TestTTextTopologicalFunctions(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02], [AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02], [AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, argument, expected", @@ -1819,9 +1746,7 @@ class TestTTextPositionFunctions(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02], [AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02], [AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, argument, expected", @@ -1905,9 +1830,7 @@ def test_is_over_or_after(self, temporal, argument, expected): class TestTTextComparisons(TestTText): tt = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - other = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + other = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") def test_eq(self): _ = self.tt == self.other @@ -1932,9 +1855,7 @@ class TestTTextEverAlwaysComparisons(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") @pytest.mark.parametrize( "temporal, expected", @@ -1989,9 +1910,7 @@ class TestTTextTemporalComparisons(TestTText): tti = TTextInst("AAA@2019-09-01") ttds = TTextSeq("{AAA@2019-09-01, BBB@2019-09-02}") tts = TTextSeq("[AAA@2019-09-01, BBB@2019-09-02]") - ttss = TTextSeqSet( - "{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}" - ) + ttss = TTextSeqSet("{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}") argument = TTextSeq("[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]") @pytest.mark.parametrize( @@ -2018,9 +1937,7 @@ def test_temporal_equal_temporal(self, temporal, expected): (tts, TBoolSeq("[True@2019-09-01, False@2019-09-02]")), ( ttss, - TBoolSeqSet( - "{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}" - ), + TBoolSeqSet("{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], @@ -2054,9 +1971,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): (tts, TBoolSeq("[False@2019-09-01, True@2019-09-02]")), ( ttss, - TBoolSeqSet( - "{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}" - ), + TBoolSeqSet("{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}"), ), ], ids=["Instant", "Discrete Sequence", "Sequence", "SequenceSet"], diff --git a/tests/temporal/interpolation_test.py b/tests/temporal/interpolation_test.py index 308865fc..8e30108e 100644 --- a/tests/temporal/interpolation_test.py +++ b/tests/temporal/interpolation_test.py @@ -1,6 +1,7 @@ +import pytest + from pymeos import TInterpolation from tests.conftest import TestPyMEOS -import pytest class TestTInterpolation(TestPyMEOS):