Skip to content

Bump PyMEOS to MEOS 1.4 (work in progress) - #81

Draft
estebanzimanyi wants to merge 27 commits into
masterfrom
bump/meos-1.4
Draft

estebanzimanyi wants to merge 27 commits into
masterfrom
bump/meos-1.4

Conversation

@estebanzimanyi

@estebanzimanyi estebanzimanyi commented May 14, 2026 •

Copy link
Copy Markdown
Member

Bind PyMEOS to the MEOS master surface

PyMEOS 1.4.0a1 requires pymeos-cffi 1.4.0a1 or later and calls MEOS master's
names and signatures. Text, timestamp, date and interval input and output go
through cstring_to_text, text_to_cstring, timestamptz_in, date_in and
interval_in; multiplication through the mul_* family; the conversions to an
instant, sequence or sequence set through temporal_as_; the temporal
distance of numbers through the tdistance_
family, which takes an int for a
TInt and a float for a TFloat; and the box nearest approach distance of a
temporal point through nad_tgeo_stbox.

The spatial relationships drop their restr and atvalue arguments, and the
distance, length, speed and nearest approach functions take spheroid=True,
the MobilityDB default. The tiling and split functions pass
border_inc=True, the MobilityDB default, so a value on the upper border
lands in the tile that starts there and time_split_n answers an (n+1)th
tile holding the end value when the end is inclusive. Set and span set
accessors read the array from the (array, count) pair the functions return,
and the time distances convert the returned interval to a timedelta.

Build the all-families MEOS and its catalog in the test workflow

The PyMEOS-CFFI cdef covers every optional MEOS family and is projected from
the MEOS-API catalog, so the test workflow derives the catalog once with the
shared provision-meos action, from the MobilityDB branch the package version
maps to, and each test job builds libmeos with every family: through
provision-meos on Linux and with -DALL=ON on macOS. PyMEOS-CFFI's header is
projected from that catalog and the installed library before it is built.

Align the test expectations with MEOS master

MF-JSON writes the full ISO 8601 offset (+00:00) and states the CRS of a
geography; the temporal hash values are those temporal_hash answers; the
split tests expect the tile that holds a value on the upper border; and the
min and max restrictions, which MobilityDB defines for tint, tbigint, tfloat
and ttext, raise for tbool and the temporal points.

The adjacent instant of the tint topological test takes the value 2 at the
same timestamp: two instants at different timestamps are apart in time, so
their boxes are not adjacent.

Test the space tiles and the value-time tiles

STBox.tile of a trip's box answers the 5 km space tiles of the trip, with
their space dimension, and TGeomPoint.tile answers the trip's pieces in them.
TBox.tile answers the value-time tiles in value order within each day,
covering the box's last day and no value band beyond its upper value.

Format the README examples as Ruff 0.17 does

Ruff 0.17 formats the Python code blocks of Markdown files, so the README
examples take its double quotes and wrapping. The UP038 rule is gone from Ruff
and leaves the ignore list.

Test every aggregator on two overlapping inputs

tests/aggregators runs each aggregator of pymeos.aggregators on two inputs that
overlap in time, so every result holds a stretch where both contribute and a
stretch where one does: the boolean, number and text temporal aggregates, the
three extents, the instant and period counts, the instantaneous time union, and
an incremental aggregation against the one-call form.

Witness: on PyMEOS-CFFI regenerated from MobilityDB master 1eca005aeb the 18
cases pass, and 16 of them fail on the surface of master adbb2ebad1, where each
aggregation starts from a None state the transition wrapper casts unguarded.
Measured: each expected value checks by its definition on the two inputs, the
integer sum being 1, then 1 + 2 = 3 from 2000-01-02, then 3 + 2 = 5 at
2000-01-03, then 2 to 2000-01-04. The suite passes 4471 of 4471.

Aggregate continuous time through the span union transition functions

TimeContinuousUnionAggregator aggregates as TimeInstantaneousUnionAggregator
does: span_union_transfn and spanset_union_transfn add each span or span set to
the state, which starts as None, and spanset_union_finalfn finishes it.
union_spanset_span and union_spanset_spanset are the binary unions of two
values, and MEOS refuses a NULL span set there, so they cannot start an
aggregation.

Witness: the union of [2000-01-01, 2000-01-03] and [2000-01-02, 2000-01-04]
aggregates to {[2000-01-01, 2000-01-04]}, a case added to tests/aggregators;
through union_spanset_span the first add raises TypeError: an integer is
required, from casting the None state the wrapper does not guard. The suite
passes 4472 of 4472.

1-ARIjitS and others added 2 commits May 14, 2026 17:00
changed function signature from distance_datespanset_datespan to distance_datespan_datespan for datespan instance in distance fucntion of datespan class
Three small fixes to bring PR #72 to a green-enough state for review:

- pymeos/mixins/comparison.py and pymeos/mixins/simplify.py imported
  Temporal at module-import time from ..temporal, which now creates a
  circular import because the temporal package re-exports the mixins.
  Move both to TYPE_CHECKING and rely on string annotations
  (already enabled by 'from __future__ import annotations').

- tests/main/tfloat_test.py::test_temporal_equal_int referenced
  temporal_equal_1, a method that has never existed. The intended
  method is temporal_equal; tfloat already has it.

With these and the PyMEOS-CFFI commit that adds the Datum helpers
and the int *count auto-detect, pytest is 4472 / 4482 (10 failures
remaining are pre-existing test fixture issues: tfloat fixtures
expect True for 1.5 == 1, and a handful of TBool assertion
mismatches that pre-date PR #72).
# Conflicts:
#	pymeos/collections/time/datespan.py
ubuntu-latest is on noble (24.04) which no longer ships
postgresql-server-dev-14. Same fix that PyMEOS-CFFI #17 already
applied (commit a0a4149).
ruff format prefers ternary expressions without surrounding parens.
The merge with master pulled in pre-ruff-format code that violated
the convention; this aligns the affected files with the rest of the
codebase.
The previous env: github.base_ref || github.ref_name resolved to
'master' for any PR, so a 1.3 / 1.4 PyMEOS PR would pull master's
MobilityDB + PyMEOS-CFFI even though the matching code lives on the
head branch. Try the head branch first and fall back to base_ref so
push events on master keep working.
Mirror PyMEOS-CFFI's pr_build approach: parse pymeos/__init__.py for
the version string, map it to stable-X.Y, fall back to master if the
stable branch doesn't exist. This stops the workflow from cloning
MobilityDB master on a 1.3 PR.
Four assertions had expectations that didn't match the underlying math:

- tests/collections/time/dateset_test.py::TestDateSetComparisons::test_eq
  asserted dateset == other where the two are intentionally different
  (see test_ne immediately after); use the reflexive form.

- tests/main/tfloat_test.py::test_temporal_equal_int passes
  TFloatSeq('[1.5, 2.5]').temporal_equal(1). The fixture expected
  True at start (1.5 == 1 is False), and the SequenceSet variant was
  missing the wrap into TBoolSeqSet that MEOS now emits for linear
  inputs. Updated to all-False, wrapped correctly.

- tests/main/tfloat_test.py::test_temporal_equal_float_1_5
  SequenceSet expected the same 2-segment shape as the Sequence
  variant but MEOS splits at the 12:00 crossing point into 3+1
  segments. Updated to the actual output.

- tests/main/tfloat_test.py::test_temporal_not_equal_int_1 asserted
  False at start and True at end. For [1.5, 2.5] linearly varying,
  != 1 is True everywhere. Updated to all-True.

Pytest now 4482 / 4482 (100%).
estebanzimanyi added a commit that referenced this pull request May 14, 2026
The 1.4 surface (PR #81) cdef's meos_cbuffer.h / meos_pose.h /
meos_rgeo.h, which only land in /usr/local/include when the build
enables those features. Without them the cffi step bails on
FileNotFoundError. Mirrors the PyMEOS-CFFI pr_build.yml flags.
@estebanzimanyi
estebanzimanyi force-pushed the bump/meos-1.4 branch 3 times, most recently from 6c7b804 to ecca684 Compare May 23, 2026 07:17
PyMEOS 1.4.0a1 requires pymeos-cffi 1.4.0a1 or later and calls MEOS master's
names and signatures. Text, timestamp, date and interval input and output go
through cstring_to_text, text_to_cstring, timestamptz_in, date_in and
interval_in; multiplication through the mul_* family; the conversions to an
instant, sequence or sequence set through temporal_as_*; the temporal
distance of numbers through the tdistance_* family, which takes an int for a
TInt and a float for a TFloat; and the box nearest approach distance of a
temporal point through nad_tgeo_stbox.

The spatial relationships drop their restr and atvalue arguments, and the
distance, length, speed and nearest approach functions take spheroid=True,
the MobilityDB default. The tiling and split functions pass
border_inc=True, the MobilityDB default, so a value on the upper border
lands in the tile that starts there and time_split_n answers an (n+1)th
tile holding the end value when the end is inclusive. Set and span set
accessors read the array from the (array, count) pair the functions return,
and the time distances convert the returned interval to a timedelta.
@estebanzimanyi
estebanzimanyi force-pushed the bump/meos-1.4 branch 2 times, most recently from 72fff80 to d0e9cf6 Compare October 20, 2026 12:17
The PyMEOS-CFFI cdef covers every optional MEOS family and is projected from
the MEOS-API catalog, so the test workflow derives the catalog once with the
shared provision-meos action, from the MobilityDB branch the package version
maps to, and each test job builds libmeos with every family: through
provision-meos on Linux and with -DALL=ON on macOS. PyMEOS-CFFI's header is
projected from that catalog and the installed library before it is built.
MF-JSON writes the full ISO 8601 offset (+00:00) and states the CRS of a
geography; the temporal hash values are those temporal_hash answers; the
split tests expect the tile that holds a value on the upper border; and the
min and max restrictions, which MobilityDB defines for tint, tbigint, tfloat
and ttext, raise for tbool and the temporal points.

The adjacent instant of the tint topological test takes the value 2 at the
same timestamp: two instants at different timestamps are apart in time, so
their boxes are not adjacent.
STBox.tile of a trip's box answers the 5 km space tiles of the trip, with
their space dimension, and TGeomPoint.tile answers the trip's pieces in them.
TBox.tile answers the value-time tiles in value order within each day,
covering the box's last day and no value band beyond its upper value.
Ruff 0.17 formats the Python code blocks of Markdown files, so the README
examples take its double quotes and wrapping. The UP038 rule is gone from Ruff
and leaves the ignore list.
tests/aggregators runs each aggregator of pymeos.aggregators on two inputs that
overlap in time, so every result holds a stretch where both contribute and a
stretch where one does: the boolean, number and text temporal aggregates, the
three extents, the instant and period counts, the instantaneous time union, and
an incremental aggregation against the one-call form.

Witness: on PyMEOS-CFFI regenerated from MobilityDB master 1eca005aeb the 18
cases pass, and 16 of them fail on the surface of master adbb2ebad1, where each
aggregation starts from a None state the transition wrapper casts unguarded.
Measured: each expected value checks by its definition on the two inputs, the
integer sum being 1, then 1 + 2 = 3 from 2000-01-02, then 3 + 2 = 5 at
2000-01-03, then 2 to 2000-01-04. The suite passes 4471 of 4471.
TimeContinuousUnionAggregator aggregates as TimeInstantaneousUnionAggregator
does: span_union_transfn and spanset_union_transfn add each span or span set to
the state, which starts as None, and spanset_union_finalfn finishes it.
union_spanset_span and union_spanset_spanset are the binary unions of two
values, and MEOS refuses a NULL span set there, so they cannot start an
aggregation.

Witness: the union of [2000-01-01, 2000-01-03] and [2000-01-02, 2000-01-04]
aggregates to {[2000-01-01, 2000-01-04]}, a case added to tests/aggregators;
through union_spanset_span the first add raises TypeError: an integer is
required, from casting the None state the wrapper does not guard. The suite
passes 4472 of 4472.

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants