Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,11 @@ Write the date in place of the "Unreleased" in the case a new version is release
retry cannot fix: an unsupported URL scheme and an invalid request such as an
illegal header value.

### Fixed

- The metadata revisions endpoint now reports the total revision count, so
all revisions can be paged through via the API.


## v0.2.11 (2026-05-27)

Expand Down
14 changes: 14 additions & 0 deletions tests/test_writing.py
Original file line number Diff line number Diff line change
Expand Up @@ -473,6 +473,20 @@ def test_metadata_revisions(tree):
ac.metadata_revisions.delete_revision(1)


def test_metadata_revisions_count(tree):
with Context.from_app(build_app(tree)) as context:
client = from_context(context)
ac = client.write_array([1, 2, 3], key="paginate_me")
ac.update_metadata(metadata={"a": 1})
ac.update_metadata(metadata={"a": 2})
ac.update_metadata(metadata={"a": 3})
# `len` reads the total count from the server, which was always 0 before.
assert len(ac.metadata_revisions) == 3
# Revisions are returned ordered by revision number.
revision_numbers = [r["revision_number"] for r in ac.metadata_revisions[:]]
assert revision_numbers == sorted(revision_numbers)


def test_replace_metadata(tiled_websocket_context):
context = tiled_websocket_context
client = from_context(context)
Expand Down
11 changes: 11 additions & 0 deletions tiled/catalog/adapter.py
Original file line number Diff line number Diff line change
Expand Up @@ -981,6 +981,17 @@ async def revisions(self, offset: int = 0, limit=None):
).all()
return [Revision.from_orm(o[0]) for o in revision_orms]

async def revisions_count(self) -> int:
"Get the total number of revisions for this node."
async with self.context.session() as db:
return (
await db.execute(
select(func.count())
.select_from(orm.Revision)
.where(orm.Revision.node_id == self.node.id)
)
).scalar_one()

async def delete(self, recursive=False, external_only=True):
"""Delete the Node, its descendants, and associated DataSources and Assets

Expand Down
2 changes: 1 addition & 1 deletion tiled/server/core.py
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ async def construct_revisions_response(
},
}
data.append(item)
count = len(data)
count = await entry.revisions_count()
links = pagination_links(base_url, route, path_parts, page, None, count)
return schemas.Response(data=data, links=links, meta={"count": count})

Expand Down
Loading