)]}'
{
  "log": [
    {
      "commit": "154288fb71a601b653804778f45e5781224038df",
      "tree": "6cd879dba91892d05f672da669d90288008bc974",
      "parents": [
        "23aa9a93c0996cbcbc93dc4354d0d86512283f61"
      ],
      "author": {
        "name": "Neelesh Salian",
        "email": "nssalian@users.noreply.github.com",
        "time": "Mon Jul 27 11:40:19 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 20:40:19 2026 +0200"
      },
      "message": "Convert `FileFormatModel` from `ABC` to `typing.Protocol` (#3692)\n\nCloses #3100 \n\n## Rationale for this change\n\n`FileFormatModel` had only abstract methods (no shared implementation),\nso an `ABC` was heavier than needed. This PR converts it to\n`typing.Protocol`, which is the more Pythonic pattern for a pure\ninterface. `FileFormatWriter` remains an `ABC` since it has shared\n`__enter__`/`__exit__`/`result` implementations that inheritance carries\nfor free. `FileFormatFactory` is unchanged - it matches the existing\n`AuthManagerFactory` pattern.\n\n## Changes\n\nNew format implementations can now conform structurally without\ninheriting from `FileFormatModel`. Net: 2 `ABC`s → 1 `ABC` + 1\n`Protocol`. No signature change for existing callers;\n`ParquetFormatModel(FileFormatModel)` inheritance is retained\n(`Protocol` supports explicit conformance).\n\n## Are these changes tested?\n\nYes. `tests/io/test_fileformat.py` adds two tests using a shared\n`_StructuralModel` helper:\n\n- `test_file_format_model_is_protocol` - a structurally-conforming class\n(no inheritance) passes `isinstance()` against `FileFormatModel`.\n- `test_structural_model_works_with_factory` - a structurally-conforming\nclass can be registered and retrieved via `FileFormatFactory`\nend-to-end.\n\n## Are there any user-facing changes?\n\nNo. Default behavior is unchanged."
    },
    {
      "commit": "23aa9a93c0996cbcbc93dc4354d0d86512283f61",
      "tree": "f6681522a074321c19d82a2c45f4ae550619af85",
      "parents": [
        "a8f27713f1b5122abee2acf030263478762210ba"
      ],
      "author": {
        "name": "Aaron Niskode-Dossett",
        "email": "dossett@gmail.com",
        "time": "Mon Jul 27 13:38:37 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 20:38:37 2026 +0200"
      },
      "message": "Make partition expression evaluation stateless (#3664)\n\n*I used CODEX to analyze this problem and create this PR. I\u0027ve reviewed\nthe code and tests and stand by them. This summary is written completely\nby a human (me) other than very light copy editing by an LLM.*\n\nCurrently, because `_ExpressionEvaluator` can\u0027t be safely shared one is\ncreated per file. That\u0027s expensive relative to actually evaluating the\nexpression. This change makes `_ExpressionEvaluator` shareable by moving\nthe mutable parts into a new `_ExpressionEvaluationVisitor` which stays\nlocal to the per-file work of evaluation.\n\nThese benchmarks are showing improvements in sub-second times, but in\nthe production workloads I tested this on it did translate to real wall\nclock improvement. But irrespective of performance gains the new\n`_ExpressionEvaluator` is safer since nothing was preventing its\naccidental concurrent reuse in the future.\n\nCODEX-generated summary follows:\n-------\nPartition pruning currently binds the same projected expression for\nevery data file because `_ExpressionEvaluator` stores the current record\nas mutable instance state. That repeated preparation is expensive, but\nsharing the existing evaluator across workers would allow concurrent\ncalls to mix records.\n\nThis separates preparation from per-record evaluation.\n`_ExpressionEvaluator` binds the expression once, while every call\ncreates a private `_ExpressionEvaluationVisitor` containing that call\u0027s\nrecord. Manifest planning can therefore prepare one evaluator per\npartition spec and safely share it across manifests and workers. This\nprovides the construction-reuse benefit targeted by #3656 without\ndepending on files within a manifest remaining sequential, and it also\nbenefits one-file manifests.\n\n## Summary\n\n- Split the prepared expression evaluator from the call-local mutable\nvisitor.\n- Reuse one prepared partition evaluator per partition spec during\nmanifest planning.\n- Add deterministic concurrent-use, prepared-state, and planner-sharing\ncoverage.\n- Add a benchmark using a realistic 15-leaf predicate across dense and\none-file manifests.\n\n## Performance\n\nI compared this branch with `main` using the partition-evaluator\nworkload in this PR. It evaluates 1,000 files with two identity\npartition fields and a 15-leaf predicate modeling five `(event_day range\nAND region_id)` branches. Timings are medians from seven samples of five\niterations.\n\n| Manifest layout | `main` | This PR | Speedup |\n|---|---:|---:|---:|\n| 1 manifest × 1,000 files | 187.928 ms | 14.413 ms | 13.04× |\n| 1,000 manifests × 1 file | 188.000 ms | 14.584 ms | 12.89× |\n\nThe improvement comes from binding the projected partition expression\nonce per partition spec instead of once per file. This is an isolated\npartition-pruning benchmark rather than an end-to-end scan-planning\nmeasurement.\n\n## Testing\n\n- `pytest tests/expressions/test_visitors.py\ntests/table/test_partition_evaluator_planning.py\ntests/table/test_init.py` (200 passed)\n- `pytest tests/benchmark/test_partition_evaluator_benchmark.py -m\nbenchmark` (2 passed)"
    },
    {
      "commit": "a8f27713f1b5122abee2acf030263478762210ba",
      "tree": "5ceaf981c6a79f90c4587e1b9e65ef1d90a84e62",
      "parents": [
        "0f2d9f3028ba095e4ad5a90f95a98e0611d02218"
      ],
      "author": {
        "name": "Anas Khan",
        "email": "anxkhn28@gmail.com",
        "time": "Tue Jul 28 00:04:31 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 20:34:31 2026 +0200"
      },
      "message": "docs: fix undefined variable in schema evolution transaction example (#3607)\n\n\u003c!-- Fills .github/pull_request_template.md verbatim (3 H1 sections).\nNo tracking issue exists for this docs-only change, so no \"Closes #\".\n--\u003e\n\n# Rationale for this change\n\nThe \"schema evolution\" section of the Python API docs shows how to\nevolve a\nschema inside a transaction:\n\n```python\nwith table.transaction() as transaction:\n    with transaction.update_schema() as update_schema:\n        update.add_column(\"some_other_field\", IntegerType(), \"doc\")\n    # ... Update properties etc\n```\n\nThe inner context manager is bound as `update_schema`, but the body\ncalls\n`update.add_column(...)`. The name `update` is not defined in that\nscope; it is\nleft over from the preceding standalone example just above it\n(`with table.update_schema() as update:`). Copy-pasting the transaction\nsnippet\nverbatim raises `NameError: name \u0027update\u0027 is not defined`.\n\nThis changes the call to use the bound name `update_schema`, so the\ndocumented\nexample runs as written. It also matches the already-correct\n`create_table_transaction` example earlier in the same page, which uses\n`update_schema.add_column(...)`.\n\n## Are these changes tested?\n\nNo automated test: this is a one-line documentation fix with no code\nchange. I\nverified it manually against the public API:\n`Transaction.update_schema()`\nreturns an `UpdateSchema` context manager whose `add_column(path,\nfield_type,\ndoc\u003dNone, ...)` signature matches the positional call in the example, so\nthe\ncorrected snippet executes without error. `pre-commit` (markdownlint,\ncodespell,\ntrailing-whitespace/end-of-file) passes on the changed file.\n\n## Are there any user-facing changes?\n\nNo. Documentation only; there are no changes to library behavior or\npublic API."
    },
    {
      "commit": "0f2d9f3028ba095e4ad5a90f95a98e0611d02218",
      "tree": "42382e14dbaedbe4acc427e3fb6273c227e2c1d1",
      "parents": [
        "3fc777713684ca9fb01e0c1dcddd917700815ea6"
      ],
      "author": {
        "name": "R. Conner Howell",
        "email": "5731503+rchowell@users.noreply.github.com",
        "time": "Mon Jul 27 14:32:32 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 20:32:32 2026 +0200"
      },
      "message": "fix: add `iceberg_type` column for `SqlCatalog` (#3263)\n\n# Rationale for this change\n\nPyiceberg currently does not include the `iceberg_type` column in the\n`iceberg_tables` table for SQL-based catalogs. This caused an error when\nreading a SQL-based Catalog from iceberg-rust, which expected this\ncolumn. I will also update iceberg-rust to be more defensive like this\nPR.\n\nThe fix here is done exactly how iceberg-java handles this. We do an\nidempotent `ALTER TABLE iceberg_tables ADD COLUMN iceberg_type` after\nensuring `iceberg_tables` exists. We explicitly use the try/catch to\nmake it idempotent because older sqlite versions do not support `IF NOT\nEXISTS` for column creation. For newly created tables, the addition to\nthe sqlalchemy table will create the column. For existing tables, this\nbackwards-compatible schema update will hit.\n\n-\nhttps://github.com/apache/iceberg/blob/main/core/src/main/java/org/apache/iceberg/jdbc/JdbcCatalog.java#L227\n-\nhttps://github.com/apache/iceberg/blob/main/core/src/main/java/org/apache/iceberg/jdbc/JdbcUtil.java#L150\n-\nhttps://github.com/apache/iceberg/blob/main/core/src/test/java/org/apache/iceberg/jdbc/TestJdbcUtil.java#L58\n\n## Are these changes tested?\n\n**Unit Testing**\n\n1. Unit test for the migration case\n2. Unit test for new table creation and idempotency\n\n**End-to-end Testing**\n\n```sh\n# Case 1. New Catalog\n\n# Catalog definition\n$ cat ~/.pyiceberg.yaml | yq .catalog.tmp\ntype: sql\nuri: sqlite:////tmp/pyiceberg.db\n\n# Trigger initialization of catalog tables\n$ pyiceberg --catalog tmp list\n\n# Verify Schema\nsqlite\u003e .schema iceberg_tables\nCREATE TABLE iceberg_tables (\n        catalog_name VARCHAR(255) NOT NULL, \n        table_namespace VARCHAR(255) NOT NULL, \n        table_name VARCHAR(255) NOT NULL, \n        metadata_location VARCHAR(1000), \n        previous_metadata_location VARCHAR(1000), \n ----\u003e  iceberg_type VARCHAR(5), \n        PRIMARY KEY (catalog_name, table_namespace, table_name)\n);\n\n# Case 2. Existing Catalog (before fix)\n\n# This catalog was created without the fix\nsqlite\u003e .schema iceberg_tables\nCREATE TABLE iceberg_tables (\n        catalog_name VARCHAR(255) NOT NULL, \n        table_namespace VARCHAR(255) NOT NULL, \n        table_name VARCHAR(255) NOT NULL, \n        metadata_location VARCHAR(1000), \n        previous_metadata_location VARCHAR(1000), \n        PRIMARY KEY (catalog_name, table_namespace, table_name)\n);\n\n# Fix is now applied\n# ...\n\n# Trigger update by loading this catalog with these changes in pyiceberg\nsqlite\u003e .schema iceberg_tables\nCREATE TABLE iceberg_tables (\n        catalog_name VARCHAR(255) NOT NULL, \n        table_namespace VARCHAR(255) NOT NULL, \n        table_name VARCHAR(255) NOT NULL, \n        metadata_location VARCHAR(1000), \n        previous_metadata_location VARCHAR(1000),\n ----\u003e  iceberg_type VARCHAR(5),\n        PRIMARY KEY (catalog_name, table_namespace, table_name)\n);\n```\n\n## Are there any user-facing changes?\n\nNo"
    },
    {
      "commit": "3fc777713684ca9fb01e0c1dcddd917700815ea6",
      "tree": "1a862eb7c158d99a9bf67f26aa76e66f15dec2d1",
      "parents": [
        "c789a012594614209a29e683cc29deecfc38a58e"
      ],
      "author": {
        "name": "David",
        "email": "avisonlivingstone@gmail.com",
        "time": "Mon Jul 27 19:21:06 2026 +0100"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 27 20:21:06 2026 +0200"
      },
      "message": "fix: preserve dictionary encoding in `to_arrow_batch_reader` (#3595)\n\n\u003c!-- Closes #3540 --\u003e\n\n# Rationale for this change\n\n`DataScan.to_arrow_batch_reader(dictionary_columns\u003d(\"col\",))` silently\ndropped dictionary\nencoding — callers got plain string arrays instead of\n`dictionary\u003cvalues\u003dstring, indices\u003dint32\u003e`,\nwith no error or warning. The eager equivalent\n`to_arrow(dictionary_columns\u003d...)` worked\ncorrectly. This fixes the streaming path to match.\n\n**Before:**\n```python\nresult \u003d table.scan().to_arrow_batch_reader(dictionary_columns\u003d(\"label\",)).read_all()\nprint(result.schema.field(\"label\").type)\n# string  ← dictionary encoding silently lost\n```\n\n**After:**\n```python\nresult \u003d table.scan().to_arrow_batch_reader(dictionary_columns\u003d(\"label\",)).read_all()\nprint(result.schema.field(\"label\").type)\n# dictionary\u003cvalues\u003dstring, indices\u003dint32\u003e  ✓\n```\n\n**Root cause:** `_to_arrow_batch_reader_via_file_scan_tasks` built\n`target_schema` via\n`schema_to_pyarrow` (which returns plain types), then called\n`.cast(target_schema)` on the\n`RecordBatchReader`. `ArrowScan.to_record_batches` correctly yielded\ndictionary-encoded\nbatches, but the cast converted them back to plain types. The fix\nrebuilds `target_schema`\nwith `pa.dictionary(pa.int32(), field.type)` for each column in\n`dictionary_columns` before\nthe cast, so the encoding is preserved end-to-end.\n\n## Are these changes tested?\n\nYes. Added `test_to_arrow_batch_reader_preserves_dictionary_columns` in\n`tests/io/test_pyarrow.py` — writes a two-column Parquet file and\nasserts that\n`_to_arrow_batch_reader_via_file_scan_tasks` returns a\ndictionary-encoded `label` column\nwhile leaving `id` as plain `int32`.\n\n## Are there any user-facing changes?\n\nYes — `to_arrow_batch_reader(dictionary_columns\u003d...)` now correctly\nreturns dictionary-encoded\narrays for the requested columns, matching the documented behaviour and\nthe existing `to_arrow`\npath. Please apply the `changelog` label to this PR — the project has no\nchangelog file/newsfragment\nrequirement (no `CONTRIBUTING.md`); release notes are generated from\nlabeled, merged PR titles.\n\n---------\n\nCo-authored-by: davidopaogun \u003cdavidopaogun@oraion.com\u003e"
    },
    {
      "commit": "c789a012594614209a29e683cc29deecfc38a58e",
      "tree": "ad82b23a62676b0579e13b5408b5dd274696cbda",
      "parents": [
        "abdde91e318dc507acd16805b39a2f0d072f39cc"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:33:55 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:33:55 2026 +0200"
      },
      "message": "Build: Bump mkdocs-material from 9.7.6 to 9.7.7 (#3703)"
    },
    {
      "commit": "abdde91e318dc507acd16805b39a2f0d072f39cc",
      "tree": "3502dec13fb9ce0b64141ccbd53c02fcb6585be7",
      "parents": [
        "0c0b86f733b6e55f8b01cf47945ec7bdbc9f1529"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:33:34 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:33:34 2026 +0200"
      },
      "message": "Build: Bump google-auth from 2.55.2 to 2.56.0 (#3702)"
    },
    {
      "commit": "0c0b86f733b6e55f8b01cf47945ec7bdbc9f1529",
      "tree": "272c90eb57acdeab8bfb76d4559bb2f6e068f3da",
      "parents": [
        "df96d8122c9c8bf5d8469485a2fd775937af7daf"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:33:22 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:33:22 2026 +0200"
      },
      "message": "Build: Bump actions/checkout from 7.0.0 to 7.0.1 (#3701)"
    },
    {
      "commit": "df96d8122c9c8bf5d8469485a2fd775937af7daf",
      "tree": "454d73a75390ed49436a9453386f8368ff22b07c",
      "parents": [
        "0a70d0f5545652733534f343d74dc425f125bfbf"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:32:58 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:32:58 2026 +0200"
      },
      "message": "Build: Bump the codeql-action group with 2 updates (#3699)"
    },
    {
      "commit": "0a70d0f5545652733534f343d74dc425f125bfbf",
      "tree": "d1e8e8310364720a86affe26becdc587a8e85312",
      "parents": [
        "99cae04ff34dd27ea428dc1ce480cf31073364e6"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:32:44 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:32:44 2026 +0200"
      },
      "message": "Build: Bump daft from 0.7.19 to 0.7.21 (#3698)"
    },
    {
      "commit": "99cae04ff34dd27ea428dc1ce480cf31073364e6",
      "tree": "0b236802646224e1a1554023ad5de17dcc27263c",
      "parents": [
        "a30ceb318513e3e18158a0d699ad142e560ad809"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:32:30 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:32:30 2026 +0200"
      },
      "message": "Build: Bump prek from 0.4.8 to 0.4.10 (#3697)"
    },
    {
      "commit": "a30ceb318513e3e18158a0d699ad142e560ad809",
      "tree": "9ba7b50c396ba480d7061717accb919449c1dcb0",
      "parents": [
        "6dd50926a15bf986abe05db18f4016dccecbd2d1"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:32:18 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:32:18 2026 +0200"
      },
      "message": "Build: Bump huggingface-hub from 1.23.0 to 1.24.0 (#3696)"
    },
    {
      "commit": "6dd50926a15bf986abe05db18f4016dccecbd2d1",
      "tree": "ae1471a2a60e3fcae2854c0349956e78e880ec13",
      "parents": [
        "d2c34d0ff4eb2ce9b0c068611fdeb3f3ad569e2f"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 25 20:32:06 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 25 20:32:06 2026 +0200"
      },
      "message": "Build: Bump jupyterlab from 4.6.1 to 4.6.2 (#3694)\n\nBumps [jupyterlab](https://github.com/jupyterlab/jupyterlab) from 4.6.1\nto 4.6.2.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/releases\"\u003ejupyterlab\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev4.6.2\u003c/h2\u003e\n\u003ch2\u003e4.6.2\u003c/h2\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/compare/v4.6.1...f1beab4a2027af4719d6edc07d52d6cf5a39a432\"\u003eFull\nChangelog\u003c/a\u003e)\u003c/p\u003e\n\u003ch3\u003eSecurity patches\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eGHSA-gx64-gj6p-pc4c: Image viewer allows XSS when opening malicious\nimage in new browser tab\u003c/li\u003e\n\u003cli\u003eGHSA-89vp-jrxv-24w8: PyPI extension blocklist package-name\ncanonicalization bypass\u003c/li\u003e\n\u003cli\u003eGHSA-h5v5-8746-g7mm: PluginManager lock-rule enforcement bypass\u003c/li\u003e\n\u003cli\u003eGHSA-pppj-hq3g-57pj: Cross-site scripting (XSS) via crafted settings\nfile (\u003ccode\u003eoverrides.json\u003c/code\u003e)\u003c/li\u003e\n\u003cli\u003eGHSA-whvh-wf3x-g77j: Allowlist/blocklist check in\n\u003ccode\u003ePyPIExtensionManager.install()\u003c/code\u003e not enforced for direct\ncallers (missing \u003ccode\u003eawait\u003c/code\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBugs fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eBackport of security patches to \u003ccode\u003e4.6.x\u003c/code\u003e branch \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19185\"\u003e#19185\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e,\n\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eFix resolving platform-specific shortcuts in keyboard shortcuts \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19112\"\u003e#19112\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eClear stale Table of Contents error markers \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19143\"\u003e#19143\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eFix stale document load after rename during initialization \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19144\"\u003e#19144\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eFix notebook initialization stealing focus \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19149\"\u003e#19149\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eFix spurious 3s kernel restart delay \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19126\"\u003e#19126\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/afshin\"\u003e\u003ccode\u003e@​afshin\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eStabilize Open in Terminal Galata test on Firefox \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19152\"\u003e#19152\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eFix bottom activity bar restoring as collapsed \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19136\"\u003e#19136\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eHandle invalid file browser drag target \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19122\"\u003e#19122\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/GagandeepSingh20\"\u003e\u003ccode\u003e@​GagandeepSingh20\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eStabilize flaky Firefox notebook Galata tests \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19008\"\u003e#19008\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eMaintenance and upkeep improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eUpdate Jupyter Releaser GitHub Actions \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19145\"\u003e#19145\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/jtpio\"\u003e\u003ccode\u003e@​jtpio\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eDocumentation improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix a typo in release notes \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19116\"\u003e#19116\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eUpdate migration guide - 4.6 was released \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19108\"\u003e#19108\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eOther merged PRs\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eBump brace-expansion from 1.1.11 to 1.1.16 in\n/jupyterlab/tests/mock_packages/test_no_hyphens \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19179\"\u003e#19179\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/apps/dependabot\"\u003e\u003ccode\u003e@​dependabot[bot]\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eBump axios from 1.16.0 to 1.18.1 \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/pull/19178\"\u003e#19178\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/apps/dependabot\"\u003e\u003ccode\u003e@​dependabot[bot]\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eContributors to this release\u003c/h3\u003e\n\u003cp\u003eThe following people contributed discussions, new ideas, code and\ndocumentation contributions, and review.\nSee \u003ca\nhref\u003d\"https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports\"\u003eour\ndefinition of contributors\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/graphs/contributors?from\u003d2026-06-29\u0026amp;to\u003d2026-07-21\u0026amp;type\u003dc\"\u003eGitHub\ncontributors page for this release\u003c/a\u003e)\u003c/p\u003e\n\u003cp\u003e\u003ca href\u003d\"https://github.com/afshin\"\u003e\u003ccode\u003e@​afshin\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyterlab%2Fjupyterlab+involves%3Aafshin+updated%3A2026-06-29..2026-07-21\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca\nhref\u003d\"https://github.com/GagandeepSingh20\"\u003e\u003ccode\u003e@​GagandeepSingh20\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyterlab%2Fjupyterlab+involves%3AGagandeepSingh20+updated%3A2026-06-29..2026-07-21\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/jtpio\"\u003e\u003ccode\u003e@​jtpio\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyterlab%2Fjupyterlab+involves%3Ajtpio+updated%3A2026-06-29..2026-07-21\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyterlab%2Fjupyterlab+involves%3Akrassowski+updated%3A2026-06-29..2026-07-21\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyterlab%2Fjupyterlab+involves%3AMUFFANUJ+updated%3A2026-06-29..2026-07-21\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/150ba51f1c840edc399597a86a6fc3ed24ef60be\"\u003e\u003ccode\u003e150ba51\u003c/code\u003e\u003c/a\u003e\n[ci skip] Publish 4.6.2\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/f1beab4a2027af4719d6edc07d52d6cf5a39a432\"\u003e\u003ccode\u003ef1beab4\u003c/code\u003e\u003c/a\u003e\nBackport of security patches to \u003ccode\u003e4.6.x\u003c/code\u003e branch (\u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19185\"\u003e#19185\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/abdd427f25fb2bd912b3549056795c420b8bd48c\"\u003e\u003ccode\u003eabdd427\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19112\"\u003e#19112\u003c/a\u003e\non branch 4.6.x (Fix resolving platform-specific shortcuts...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/98a615c45e9c0cc19034843bde2847b82d2c5a83\"\u003e\u003ccode\u003e98a615c\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19143\"\u003e#19143\u003c/a\u003e\non branch 4.6.x (Clear stale Table of Contents error marke...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/1ec91a43a74b5750abec50dd89732ad169545023\"\u003e\u003ccode\u003e1ec91a4\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19179\"\u003e#19179\u003c/a\u003e\non branch 4.6.x (Bump brace-expansion from 1.1.11 to 1.1.1...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/8d66183966a5f155683df6ebd4717b089e0935d4\"\u003e\u003ccode\u003e8d66183\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19178\"\u003e#19178\u003c/a\u003e\non branch 4.6.x (Bump axios from 1.16.0 to 1.18.1) (\u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19180\"\u003e#19180\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/34ca550c634df450f9319aa1fec87c1698f7e98a\"\u003e\u003ccode\u003e34ca550\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19144\"\u003e#19144\u003c/a\u003e\non branch 4.6.x (Fix stale document load after rename duri...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/172a7f6886c3e0fd935a2237a743a1446e1a8ae4\"\u003e\u003ccode\u003e172a7f6\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19149\"\u003e#19149\u003c/a\u003e\non branch 4.6.x (Fix notebook initialization stealing focu...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/34e178282b6536cee8bcff5a8eddc5f9407c3cd2\"\u003e\u003ccode\u003e34e1782\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19126\"\u003e#19126\u003c/a\u003e\non branch 4.6.x (Fix spurious 3s kernel restart delay) (\u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/1\"\u003e#1\u003c/a\u003e...\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/commit/57e5afd1d19952c22fd0dce414b955061a3e2c4e\"\u003e\u003ccode\u003e57e5afd\u003c/code\u003e\u003c/a\u003e\nBackport PR \u003ca\nhref\u003d\"https://redirect.github.com/jupyterlab/jupyterlab/issues/19152\"\u003e#19152\u003c/a\u003e\non branch 4.6.x (Stabilize Open in Terminal Galata test on...\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/jupyterlab/jupyterlab/compare/@jupyterlab/lsp@4.6.1...@jupyterlab/lsp@4.6.2\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003djupyterlab\u0026package-manager\u003duv\u0026previous-version\u003d4.6.1\u0026new-version\u003d4.6.2)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\nYou can disable automated security fix PRs for this repo from the\n[Security Alerts\npage](https://github.com/apache/iceberg-python/network/alerts).\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "d2c34d0ff4eb2ce9b0c068611fdeb3f3ad569e2f",
      "tree": "2ac56c18ff4b2a1be317054e5600f9d154d4e818",
      "parents": [
        "82be040f9a3179a3c5ffa81050267419d5fb3ee3"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 24 11:22:27 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 24 11:22:27 2026 -0700"
      },
      "message": "Build: Bump pyasn1 from 0.6.3 to 0.6.4 (#3693)"
    },
    {
      "commit": "82be040f9a3179a3c5ffa81050267419d5fb3ee3",
      "tree": "388007c0ca4066dec189fa6bd982c85938975fad",
      "parents": [
        "f16246aa23c747a32809a428b8f739a33ce0668c"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jul 19 21:25:35 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 21:25:35 2026 +0200"
      },
      "message": "Build: Bump the codeql-action group with 2 updates (#3686)"
    },
    {
      "commit": "f16246aa23c747a32809a428b8f739a33ce0668c",
      "tree": "2c716ec31a17b0ea87bf1144a98c32144f5c9e91",
      "parents": [
        "c08d294721c37001bcf18f8c07f4944740282663"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jul 19 21:25:20 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 21:25:20 2026 +0200"
      },
      "message": "Build: Bump thrift from 0.23.0 to 0.24.0 (#3684)"
    },
    {
      "commit": "c08d294721c37001bcf18f8c07f4944740282663",
      "tree": "9d411b4320e28f56444d7fa73fc0b66974e3e909",
      "parents": [
        "921e1118f7bd45b22e59144d5295b7cea30d3bee"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jul 19 21:25:09 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 21:25:09 2026 +0200"
      },
      "message": "Build: Bump mkdocstrings from 1.0.5 to 1.0.6 (#3683)"
    },
    {
      "commit": "921e1118f7bd45b22e59144d5295b7cea30d3bee",
      "tree": "660d064f469166133c6e246f9fe251828c7df88d",
      "parents": [
        "1173e4591a7b9f09d1ec23aa6bd2f89560ed41eb"
      ],
      "author": {
        "name": "Neelesh Salian",
        "email": "nssalian@users.noreply.github.com",
        "time": "Sat Jul 18 23:10:42 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 08:10:42 2026 +0200"
      },
      "message": "Implement `ParquetFormatModel` and update `write_file` to use the format API (#3381)\n\nContinued work on https://github.com/apache/iceberg-python/issues/3100\n\n## PR Description\n\nFollow-up to #3119. Implements `ParquetFormatWriter` and\n`ParquetFormatModel`, registers Parquet in the `FileFormatFactory`, and\nrewrites `write_file` to dispatch through the factory using the\n`write.format.default` table property. Future formats can be added in a\nsimilar way.\n\n## Rationale for this change\n\nThe `write.format.default` table property was never read - the write\npath was hardcoded to Parquet. This PR makes the property functional.\nAlso threads `file_format` through `_to_requested_schema` /\n`ArrowProjectionVisitor` / `_construct_field` so field ID metadata keys\nare correct per format (`PARQUET:field_id` for Parquet, `iceberg.id`\nplus `iceberg.required` for ORC), preparing the write path for ORC\nsupport without changing default behavior.\n\n## Are these changes tested?\n\n- `tests/io/test_format_writers.py` adds parametrized tests modeled\nafter Java\u0027s `BaseFormatModelTests` covering round-trip, statistics,\nnull handling, context manager caching, close idempotency,\nclose-without-write, and ORC vs Parquet field ID dispatch.\n- `tests/io/test_pyarrow.py` adds `test_write_file_parquet_round_trip`\nand `test_write_file_dispatches_on_write_format_default` exercising the\nfull `write_file` path.\n\n## Are there any user-facing changes?\n\nNo. Default behavior is unchanged. Setting `write.format.default` to an\nunregistered format now raises a `ValueError`."
    },
    {
      "commit": "1173e4591a7b9f09d1ec23aa6bd2f89560ed41eb",
      "tree": "f89ebb8d5b0094aa35712c470307abccc2e4f8a2",
      "parents": [
        "b697b026b5d90e5449cc8e81ad801894efe6e0b4"
      ],
      "author": {
        "name": "Alex Stephen",
        "email": "1325798+rambleraptor@users.noreply.github.com",
        "time": "Sat Jul 18 23:09:42 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 08:09:42 2026 +0200"
      },
      "message": "Only run integration tests on Python changes (#3610)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${GITHUB_ISSUE_ID} --\u003e\n\n# Rationale for this change\nI noticed on my AGENTS.md change that it ran the integration tests. We\nhaven\u0027t (yet) reached issues from ASF on runner usage, but this is a\nreally easy win. Markdown changes shouldn\u0027t trigger integration tests.\n\n## Are these changes tested?\nExpecting a no-op. \n\n## Are there any user-facing changes?\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "b697b026b5d90e5449cc8e81ad801894efe6e0b4",
      "tree": "ea57a2a81828f770017a164fc95f814dff5e5442",
      "parents": [
        "1a047720c2973b515ee2fe0b7b1cdbdb4cbcb04f"
      ],
      "author": {
        "name": "Anas Khan",
        "email": "anxkhn28@gmail.com",
        "time": "Sun Jul 19 11:38:03 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 08:08:03 2026 +0200"
      },
      "message": "fix: preserve write_default when applying a name mapping (#3601)\n\n# Rationale for this change\n\n`NameMappingProjectionVisitor.field` (the visitor behind\n`apply_name_mapping`)\nrebuilds each `NestedField`, but it passed the field\u0027s write default\nunder the\nkeyword `initial_write\u003d`:\n\n```python\nreturn NestedField(\n    field_id\u003dfield_partner.field_id,\n    name\u003dfield.name,\n    field_type\u003dfield_result,\n    required\u003dfield.required,\n    doc\u003dfield.doc,\n    initial_default\u003dfield.initial_default,\n    initial_write\u003dfield.write_default,   # \u003c- no such parameter\n)\n```\n\n`NestedField.__init__` has no `initial_write` parameter; its\nwrite-default\nkeyword is `write_default`. Because `NestedField` is a Pydantic model,\nthe\nunknown `initial_write` key is absorbed by the `**data` catch-all and\nsilently\nignored, so `apply_name_mapping` dropped every field\u0027s `write_default`\nto\n`None` (while `initial_default` was preserved). Every other place that\nrebuilds\na `NestedField` (for example in `pyiceberg/table/update/schema.py`)\nalready uses\n`write_default\u003d`; this was the one call site out of step with the\nconstructor.\n\nThe fix passes `write_default\u003dfield.write_default` to match the\nconstructor\ncontract.\n\n## Are these changes tested?\n\nYes. Added `test_mapping_preserves_field_defaults` in\n`tests/table/test_name_mapping.py`, which builds a schema whose field\ncarries\nboth `initial_default` and `write_default`, runs it through\n`apply_name_mapping`, and asserts both values survive on the mapped\nfield. It\nfails before the change (`write_default` comes back `None`) and passes\nafter.\n\n- `tests/table/test_name_mapping.py`: 13 passed\n- `tests/io/test_pyarrow_visitor.py` and `tests/test_schema.py`: 388\npassed\n(the PyArrow name-mapping visitor and schema, the current caller\nsurface)\n\nIntegration tests (Docker + Spark) were not run in this environment; the\nchange\nis pure Python type-plumbing fully exercised by the unit tests above.\n\n## Are there any user-facing changes?\n\nNo observable change in the current code paths. The only caller today is\n`pyarrow_to_schema` -\u003e `apply_name_mapping` (`pyiceberg/io/pyarrow.py`),\nwhich\nfeeds a PyArrow-derived schema whose fields never carry an Iceberg\n`write_default`, so nothing is dropped in practice right now. This is a\nlatent\ncorrectness fix: it prevents `write_default` from being silently\ndiscarded the\nmoment a name mapping is applied to any schema whose fields set a write\ndefault."
    },
    {
      "commit": "1a047720c2973b515ee2fe0b7b1cdbdb4cbcb04f",
      "tree": "e87fd635f30e15b12ed31c966ca0231b61906775",
      "parents": [
        "4223f4cb187e796befd61c2536e31ada4a9aa631"
      ],
      "author": {
        "name": "Koen Denecker",
        "email": "koen@polars.tech",
        "time": "Sun Jul 19 08:02:35 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 08:02:35 2026 +0200"
      },
      "message": "fix: Pass metadata location to `StaticTable` `FileIO` (#3592)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${3591} --\u003e\n\n# Rationale for this change\nSee issue #3591 - bug fix. FileIO selection fails on StaticTable because\nthe location is missing.\n\n## Are these changes tested?\nYes `make test` passes. Added a basic regression test.\n\n## Are there any user-facing changes?\nNo.\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "4223f4cb187e796befd61c2536e31ada4a9aa631",
      "tree": "c64a72fbeaacb28597faa601802f5d6ba46205cd",
      "parents": [
        "e19eca8020e9b4eeac0cbc1d85bcbf906835e6ad"
      ],
      "author": {
        "name": "Anas Khan",
        "email": "anxkhn28@gmail.com",
        "time": "Sun Jul 19 11:31:13 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 08:01:13 2026 +0200"
      },
      "message": "feat: support pyarrow float16 by widening to float on read/write (#3590)\n\n# Rationale for this change\n\nPyArrow `float16` (`halffloat`) currently raises\n`UnsupportedPyArrowTypeException` during schema conversion, because\n`_ConvertToIceberg.primitive` only handles `float32` and `float64`:\n\n```python\n\u003e\u003e\u003e import pyarrow as pa\n\u003e\u003e\u003e from pyiceberg.io.pyarrow import _ConvertToIceberg, visit_pyarrow\n\u003e\u003e\u003e visit_pyarrow(pa.float16(), _ConvertToIceberg())\npyiceberg.exceptions.UnsupportedPyArrowTypeException: Column \u0027x\u0027 has an unsupported type: halffloat\n```\n\nIceberg has no half-precision float, but `float16 -\u003e float32` is\n**lossless**: every IEEE 754 half value (including the maximum finite\nvalue 65504) is exactly representable in single precision. This mirrors\nhow the same method already widens `int8`/`int16` to `IntegerType`, and\nhow `ArrowProjectionVisitor._cast_if_needed` already widens smaller\nintegers up for cross-platform compatibility. Mapping `float16 -\u003e\nFloatType` is the float analogue, so `float16` columns round-trip\ninstead of erroring.\n\nChanges (`pyiceberg/io/pyarrow.py`):\n\n- `_ConvertToIceberg.primitive`: map `pa.float16()` -\u003e `FloatType()`.\n- `ArrowProjectionVisitor._cast_if_needed`: widen smaller float types to\nthe target type on write (parallel to the existing integer-widening\nbranch), so `float16` arrays are cast to `float32`. Narrowing falls\nthrough to the existing `promote()` handling.\n\nNo dependency changes; `pyproject.toml` / `uv.lock` are untouched and\nthe imports used were already present.\n\nA note on a design choice, deferring to maintainers: widening `float16`\nsilently (rather than erroring or gating behind a config flag) follows\nthe existing `int8`/`int16 -\u003e Integer` precedent. Happy to gate it\nbehind a config option instead if you\u0027d prefer. The new float-widening\nbranch also makes `float32 -\u003e DoubleType` actually cast the array\n(parallel to int widening), so it slightly tightens float promotion in\ngeneral, not just `float16`.\n\n## Are these changes tested?\n\nYes:\n\n- `tests/io/test_pyarrow_visitor.py::test_pyarrow_float16_to_iceberg`\nasserts the schema mapping `pa.float16() -\u003e FloatType()`.\n- `tests/io/test_pyarrow.py::test__to_requested_schema_float_promotion`\nis parametrized over `f16 -\u003e Float`, `f16 -\u003e Double`, and `f32 -\u003e\nDouble`, asserting both the written PyArrow type and that the values are\npreserved.\n\nBoth pass locally, the surrounding visitor suite and the sibling\ninteger-promotion test still pass, and `make lint` (ruff, ruff-format,\nmypy, pydocstyle, codespell, uv-lock) is clean. The integration suite\n(Docker/Spark) was not run locally.\n\n## Are there any user-facing changes?\n\nYes. PyArrow tables with `float16` columns can now be converted/written\nthrough PyIceberg (they map to Iceberg `float` and are stored as\n`float32`), where they previously raised\n`UnsupportedPyArrowTypeException`. This is purely additive; existing\n`float32`/`float64` behavior is unchanged."
    },
    {
      "commit": "e19eca8020e9b4eeac0cbc1d85bcbf906835e6ad",
      "tree": "7fc9c3c64fe79647534c7d9b99c680443451cd25",
      "parents": [
        "768a29d50a1c749e3b3455747cda151217654960"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Sun Jul 19 14:45:24 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jul 19 07:45:24 2026 +0200"
      },
      "message": "Infra: Group github/codeql-action bumps into a single dependabot PR (#3648)\n\n# Rationale for this change\n\nThus, dependabot can update these two jobs in a single PR:\n\n\nhttps://github.com/apache/iceberg-python/blob/2c7552324800f40adbeda844bbc40d3420c05a84/.github/workflows/codeql.yml#L48-L54\n\n- https://github.com/apache/infrastructure-actions/pull/1028\n\n## Are these changes tested?\n\nN/A\n\n## Are there any user-facing changes?\n\nNo"
    },
    {
      "commit": "768a29d50a1c749e3b3455747cda151217654960",
      "tree": "be8552b063aa1c8b7257b373e368eabd54aedccf",
      "parents": [
        "fea08adbf07b4ea6aac6cc4c7f59dda9c3a71c19"
      ],
      "author": {
        "name": "Alex Stephen",
        "email": "1325798+rambleraptor@users.noreply.github.com",
        "time": "Sat Jul 18 13:29:05 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:29:05 2026 +0200"
      },
      "message": "Add basic assumptions to AGENTS.md (#3552)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${GITHUB_ISSUE_ID} --\u003e\n\n# Rationale for this change\nOur AGENTS.md just talks about the security model. We get a non-trivial\namount of AI activity on this repo and our AGENTS.md should reflect some\nbasic assumptions we want for those PRs.\n\nA lot of this was inspired by [Iceberg\nAGENTS.md](https://github.com/apache/iceberg/blob/main/AGENTS.md).\n\nThis is just meant to be an initial version with some thoughts that I\u0027ve\nseen and some of the basic architecture (as seen in the Iceberg\nAGENTS.md)\n\n## Are these changes tested?\nJust Markdown.\n\n## Are there any user-facing changes?\nNo.\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e\n\n---------\n\nCo-authored-by: Fokko Driesprong \u003cfokko@apache.org\u003e"
    },
    {
      "commit": "fea08adbf07b4ea6aac6cc4c7f59dda9c3a71c19",
      "tree": "4834d5d327e6043befa400dc4b44ed57e8b6a557",
      "parents": [
        "c2093328cf9fdf0d7d1da485e9f3b0681cc2ed05"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Sun Jul 19 05:27:11 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:27:11 2026 +0200"
      },
      "message": "Support zstd blob decompression in Puffin (#3575)\n\n# Rationale for this change\n\nSupport zstd blob decompression in Puffin to enhance its specification\ncoverage.\n\n## Are these changes tested?\n\nYes. Copied a Puffin file from\nhttps://github.com/apache/iceberg/tree/main/core/src/test/resources/org/apache/iceberg/puffin/v1\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "c2093328cf9fdf0d7d1da485e9f3b0681cc2ed05",
      "tree": "a3636f5814bf9d0e7c1c87936ae90b8b13f24796",
      "parents": [
        "ea80d51cb6070f567d76984a3ac99e7753828fa6"
      ],
      "author": {
        "name": "Platon G. Gimp",
        "email": "platongimp96@gmail.com",
        "time": "Sun Jul 19 01:23:46 2026 +0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:23:46 2026 +0200"
      },
      "message": "fix: raise `ValidationError` for decimal precision outside range (#3585)\n\nCloses #3583\n\n# Rationale for this change\nAccording to the Iceberg specification, decimal precision must be\nbetween 1 and 38. Previously, `pyiceberg` silently accepted invalid\nvalues (such as `precision\u003d39` or `0`), which could lead to data\ncorruption or crashes downstream when encoding/decoding fixed-byte\ndecimals (matching the Java implementation\u0027s\n`IllegalArgumentException`).\n\nThis PR adds a defensive validation guard into `DecimalType.__init__` to\nraise a `ValidationError` when the precision is out of bounds `[1, 38]`.\n\nAdditionally, fixed an existing invalid type definition\n(`DecimalType(100, 2)`) inside `tests/test_schema.py` which was\nviolating the specification bounds and causing the new validation guard\nto trip during the integration test suite.\n\n## Are these changes tested?\nYes, added dedicated unit tests in `tests/test_types.py`:\n- `test_decimal_precision_validation` covers upper bounds\n(`precision\u003d39`), lower bounds (`precision\u003d0`, `precision\u003d-5`), and\nensures valid boundary values (`precision\u003d38`) work perfectly.\n\nAlso updated existing test assertions in `tests/test_schema.py` to use a\ncompliant precision value (`38`).\n\n## Are there any user-facing changes?\nYes, creating a `DecimalType` with an invalid precision will now\nexplicitly raise a `pyiceberg.exceptions.ValidationError` instead of\nfailing silently at runtime."
    },
    {
      "commit": "ea80d51cb6070f567d76984a3ac99e7753828fa6",
      "tree": "ab9e862adf8ce32eb5026fffa5e92d68f9cdd9d0",
      "parents": [
        "3b144a7b30b7524dfc9ae445d58acd7c743b9719"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:20:14 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:20:14 2026 +0200"
      },
      "message": "Build: Bump actions/stale from 10.3.0 to 10.4.0 (#3669)"
    },
    {
      "commit": "3b144a7b30b7524dfc9ae445d58acd7c743b9719",
      "tree": "cf559ea5170e051743feac35d40af51b9f85f635",
      "parents": [
        "c8f080c80b14aef4e91071cbe65057b70a204750"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:19:49 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:19:49 2026 +0200"
      },
      "message": "Build: Bump daft from 0.7.16 to 0.7.19 (#3671)"
    },
    {
      "commit": "c8f080c80b14aef4e91071cbe65057b70a204750",
      "tree": "9aaffc100d16e7487da5763cfd49974dc6386194",
      "parents": [
        "32074cf98f66bf8db22676dda404ed01653efa5b"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:19:29 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:19:29 2026 +0200"
      },
      "message": "Build: Bump prek from 0.4.6 to 0.4.8 (#3672)"
    },
    {
      "commit": "32074cf98f66bf8db22676dda404ed01653efa5b",
      "tree": "12bbf50d844f99291a23624c7053465a7d75cbfc",
      "parents": [
        "92d68c4b8dca4cf398d4a252bb2d058ef2070bab"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:18:38 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:18:38 2026 +0200"
      },
      "message": "Build: Bump google-auth from 2.55.1 to 2.55.2 (#3674)"
    },
    {
      "commit": "92d68c4b8dca4cf398d4a252bb2d058ef2070bab",
      "tree": "db9eea00dbb2b500bf090f16c9a44ef74b0b929d",
      "parents": [
        "3eb43845a315a1c12eb6ad3c7f41e58d1751df6a"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:18:13 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:18:13 2026 +0200"
      },
      "message": "Build: Bump huggingface-hub from 1.22.0 to 1.23.0 (#3675)"
    },
    {
      "commit": "3eb43845a315a1c12eb6ad3c7f41e58d1751df6a",
      "tree": "d09e48f7b86eca97c021a1127bd8732164f3ed83",
      "parents": [
        "832f9a68c57826834c87144b80668593049c67b2"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:17:56 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:17:56 2026 +0200"
      },
      "message": "Build: Bump boto3 from 1.43.0 to 1.43.46 (#3676)\n\nBumps [boto3](https://github.com/boto/boto3) from 1.43.0 to 1.43.46.\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/c7888d6ae67b712df9be3462eeacd2c74e9e0c44\"\u003e\u003ccode\u003ec7888d6\u003c/code\u003e\u003c/a\u003e\nMerge branch \u0027release-1.43.46\u0027\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/1479621e3e478cfaa89f3b3327702865f0370968\"\u003e\u003ccode\u003e1479621\u003c/code\u003e\u003c/a\u003e\nBumping version to 1.43.46\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/54abdb4aba7b980bf2fafd0d4e1043491eb6e63d\"\u003e\u003ccode\u003e54abdb4\u003c/code\u003e\u003c/a\u003e\nAdd changelog entries from botocore\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/75de6377d0a23c3468bfd8fc1740000599d73691\"\u003e\u003ccode\u003e75de637\u003c/code\u003e\u003c/a\u003e\nMerge branch \u0027release-1.43.45\u0027\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/d3449aa60a089a207491d34f4a6f158bac78de50\"\u003e\u003ccode\u003ed3449aa\u003c/code\u003e\u003c/a\u003e\nMerge branch \u0027release-1.43.45\u0027 into develop\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/497253d2edd8f134e3af77d12916b89acb0857ba\"\u003e\u003ccode\u003e497253d\u003c/code\u003e\u003c/a\u003e\nBumping version to 1.43.45\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/5e9768e47caf2e77116397860a2ce998041b1715\"\u003e\u003ccode\u003e5e9768e\u003c/code\u003e\u003c/a\u003e\nAdd changelog entries from botocore\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/19a915b7eecc57ddb62553f06f82a72f727259f9\"\u003e\u003ccode\u003e19a915b\u003c/code\u003e\u003c/a\u003e\nMerge branch \u0027release-1.43.44\u0027\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/1b69a0681e5bd05d3469b33bd27169d44cbb78a6\"\u003e\u003ccode\u003e1b69a06\u003c/code\u003e\u003c/a\u003e\nMerge branch \u0027release-1.43.44\u0027 into develop\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/boto/boto3/commit/b0e3f6afcdf86d589a2dfc5d53eb27a93bb72e84\"\u003e\u003ccode\u003eb0e3f6a\u003c/code\u003e\u003c/a\u003e\nBumping version to 1.43.44\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/boto/boto3/compare/1.43.0...1.43.46\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dboto3\u0026package-manager\u003duv\u0026previous-version\u003d1.43.0\u0026new-version\u003d1.43.46)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "832f9a68c57826834c87144b80668593049c67b2",
      "tree": "acb6de4add529204204e67afe487865d6e19adc6",
      "parents": [
        "63baaae2d2a68b5e6aabf9889429ce9b15d3cee1"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:17:40 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:17:40 2026 +0200"
      },
      "message": "Build: Bump bodo from 2026.6 to 2026.7 (#3677)"
    },
    {
      "commit": "63baaae2d2a68b5e6aabf9889429ce9b15d3cee1",
      "tree": "0fb6c669b8e62701bb9d12d07f53b894d4f53edc",
      "parents": [
        "30b6a3a9e75a337c580f4af50a06f27c27c41b3b"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:17:23 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:17:23 2026 +0200"
      },
      "message": "Build: Bump mkdocstrings from 1.0.4 to 1.0.5 (#3678)"
    },
    {
      "commit": "30b6a3a9e75a337c580f4af50a06f27c27c41b3b",
      "tree": "1fc5578477fcf6fa851ec515cab8a7de33d95b9a",
      "parents": [
        "48e710d20ceeeaa637d5aeae7746b787410859f8"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jul 18 22:17:06 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jul 18 22:17:06 2026 +0200"
      },
      "message": "Build: Bump google-cloud-bigquery from 3.42.1 to 3.42.2 (#3679)"
    },
    {
      "commit": "48e710d20ceeeaa637d5aeae7746b787410859f8",
      "tree": "e3457c608031fc471a25a20777a7a7e8be2c26ee",
      "parents": [
        "8a31e79228d9a8da93c162ce22f1ce044ad11273"
      ],
      "author": {
        "name": "Anas Khan",
        "email": "anxkhn28@gmail.com",
        "time": "Fri Jul 17 09:22:41 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:52:41 2026 +0200"
      },
      "message": "fix: preserve manifest min sequence number of 0 (#3660)\n\n# Rationale for this change\n\n`ManifestWriter.to_manifest_file()` computed the manifest\u0027s minimum data\nsequence number with a truthiness fallback:\n\n```python\nmin_sequence_number \u003d self._min_sequence_number or UNASSIGNED_SEQ\n```\n\nA data sequence number of `0` is a legitimate minimum for a live file\n(files\nfrom a v1 table, or the initial commit of a v2 table). Because `0` is\nfalsy,\n`or` collapses it to `UNASSIGNED_SEQ` (`-1`), i.e. it treats a real `0`\nthe same\nas \"unset\".\n\nThis diverges from the Java reference implementation, which falls back\nto\n`UNASSIGNED_SEQ` only when the value is actually unset:\n\n```java\n// ManifestWriter#toManifestFile (apache/iceberg)\nlong minSeqNumber \u003d minDataSequenceNumber !\u003d null ? minDataSequenceNumber : UNASSIGNED_SEQ;\n```\n\nThe `-1` is not harmless. When the manifest is produced by a\nmerge/compaction\n(so its `added_snapshot_id` equals the current commit snapshot id),\n`ManifestListWriter.prepare_manifest()` treats `min_sequence_number \u003d\u003d\nUNASSIGNED_SEQ` as \"no file had an assigned sequence number\" and\noverwrites it\nwith the current, higher commit sequence number\n(`pyiceberg/manifest.py`, the `if\nwrapped_manifest_file.min_sequence_number \u003d\u003d\nUNASSIGNED_SEQ:` branch). The manifest\u0027s minimum data sequence number is\nthereby\nsilently raised, which affects sequence-number-based delete-file\napplication and\nscans.\n\nThe fix uses an explicit `None` check instead of a truthiness fallback,\nmirroring the Java writer:\n\n```python\nmin_sequence_number \u003d self._min_sequence_number if self._min_sequence_number is not None else UNASSIGNED_SEQ\n```\n\n## Are these changes tested?\n\nYes. A new parametrized regression test,\n\n`tests/utils/test_manifest.py::test_write_manifest_min_sequence_number_zero`\n(format versions 1 and 2), drives a live `EXISTING` entry with\n`sequence_number\u003d0` through `ManifestWriter.existing()` and asserts that\n`to_manifest_file().min_sequence_number \u003d\u003d 0`.\n\nThe test fails before the fix (`assert -1 \u003d\u003d 0`) and passes after it.\nThis path\nhad no prior coverage: no existing test drove a live sequence-0 entry\nthrough\n`to_manifest_file()`, which is why the defect was not caught.\n\nLocal runs (unit tests):\n- `pytest tests/utils/test_manifest.py -q` -\u003e passes.\n- `pytest tests/table/test_snapshots.py\ntests/table/test_manage_snapshots.py -q`\n  -\u003e passes.\n- `make lint` (ruff, ruff-format, mypy, pydocstyle, codespell) -\u003e clean\non the\n  changed files.\n\nThe merge/compaction integration path exercised by `prepare_manifest()`\nis\ncovered by the integration suite, which requires Docker and Spark; those\nwere\nnot run locally. The new unit test exercises the same\n`to_manifest_file()` write\npath that feeds it.\n\n## Are there any user-facing changes?\n\nNo API changes. It is a correctness fix: manifests written for live\nfiles whose\nminimum data sequence number is `0` now record `0` instead of `-1`, so a\nsubsequent merge/compaction no longer silently raises the manifest\u0027s\nminimum\ndata sequence number.\n\nSigned-off-by: Anas Khan \u003c83116240+anxkhn@users.noreply.github.com\u003e"
    },
    {
      "commit": "8a31e79228d9a8da93c162ce22f1ce044ad11273",
      "tree": "9d38c376dae6c4cc9e2047db67c89cb7c9031345",
      "parents": [
        "1a8fbcc83daa941e3b8b8871d60920efbf434adb"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 05:51:14 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:51:14 2026 +0200"
      },
      "message": "Build: Bump cython from 3.2.6 to 3.2.8 (#3637)"
    },
    {
      "commit": "1a8fbcc83daa941e3b8b8871d60920efbf434adb",
      "tree": "98daa68c4bb980c52a062dc9e1da1b23109f1051",
      "parents": [
        "e408a0fd458e22f052740b6c3d6b475cd5c5c103"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 05:50:50 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:50:50 2026 +0200"
      },
      "message": "Build: Bump typing-extensions from 4.15.0 to 4.16.0 (#3639)"
    },
    {
      "commit": "e408a0fd458e22f052740b6c3d6b475cd5c5c103",
      "tree": "140e4824bad1046599b9d9eff69933a237ee6cd7",
      "parents": [
        "80d71686d39fc9cd382456984c275d42d97129c8"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Fri Jul 17 12:50:33 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:50:33 2026 +0200"
      },
      "message": "Build: Bump github/codeql-action/init and github/codeql-action/analyze from 4.36.2 to 4.36.3 (#3646)\n\n# Rationale for this change\n\n`github/codeql-action*` require the same version.\n\nI\u0027ve opened another #3648 to improve the grouping in dependabot setting.\n\n- Closes https://github.com/apache/iceberg-python/pull/3640\n- Closes https://github.com/apache/iceberg-python/pull/3636\n\n## Are these changes tested?\n\nN/A\n\n## Are there any user-facing changes?\n\nNo\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "80d71686d39fc9cd382456984c275d42d97129c8",
      "tree": "820bb605b3024d73a310d8ae37b31e5dacfc58ff",
      "parents": [
        "873250fcf74f53eea1e502f72b1f0c1059bb2345"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 05:49:52 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:49:52 2026 +0200"
      },
      "message": "Build: Bump huggingface-hub from 1.21.0 to 1.22.0 (#3641)"
    },
    {
      "commit": "873250fcf74f53eea1e502f72b1f0c1059bb2345",
      "tree": "f77b8d37252364cf6a64fdac66ac7b57d34c1799",
      "parents": [
        "aefda20f2de20acab0ae78dd9c6daf9a2cbf5f12"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 05:49:42 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:49:42 2026 +0200"
      },
      "message": "Build: Bump prek from 0.4.5 to 0.4.6 (#3642)"
    },
    {
      "commit": "aefda20f2de20acab0ae78dd9c6daf9a2cbf5f12",
      "tree": "4050314d03a87c9373a535c07f4c5c7a41955de6",
      "parents": [
        "d5a8c932d5ed96201ef06a815c5c39534cc138db"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 05:49:27 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:49:27 2026 +0200"
      },
      "message": "Build: Bump polars from 1.42.0 to 1.42.1 (#3643)"
    },
    {
      "commit": "d5a8c932d5ed96201ef06a815c5c39534cc138db",
      "tree": "bd94d1f0131c60b72036de2dab48c7856c1da2ba",
      "parents": [
        "2c7552324800f40adbeda844bbc40d3420c05a84"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Fri Jul 17 05:49:12 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Fri Jul 17 05:49:12 2026 +0200"
      },
      "message": "Build: Bump mypy-boto3-glue from 1.43.34 to 1.43.37 (#3644)\n\nBumps [mypy-boto3-glue](https://github.com/youtype/mypy_boto3_builder)\nfrom 1.43.34 to 1.43.37.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/youtype/mypy_boto3_builder/releases\"\u003emypy-boto3-glue\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e8.8.0 - Python 3.8 runtime is back\u003c/h2\u003e\n\u003ch3\u003eChanged\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e[services]\u003c/code\u003e \u003ccode\u003einstall_requires\u003c/code\u003e section is\ncalculated based on dependencies in use, so\n\u003ccode\u003etyping-extensions\u003c/code\u003e version is set properly\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[all]\u003c/code\u003e Replaced \u003ccode\u003etyping\u003c/code\u003e imports with\n\u003ccode\u003ecollections.abc\u003c/code\u003e with a fallback to \u003ccode\u003etyping\u003c/code\u003e for\nPython \u0026lt;3.9\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[all]\u003c/code\u003e Added aliases for \u003ccode\u003ebuiltins.list\u003c/code\u003e,\n\u003ccode\u003ebuiltins.set\u003c/code\u003e, \u003ccode\u003ebuiltins.dict\u003c/code\u003e, and\n\u003ccode\u003ebuiltins.type\u003c/code\u003e, so Python 3.8 runtime should work as\nexpected again (reported by \u003ca\nhref\u003d\"https://github.com/YHallouard\"\u003e\u003ccode\u003e@​YHallouard\u003c/code\u003e\u003c/a\u003e in \u003ca\nhref\u003d\"https://redirect.github.com/youtype/mypy_boto3_builder/issues/340\"\u003e#340\u003c/a\u003e\nand \u003ca\nhref\u003d\"https://github.com/Omri-Ben-Yair\"\u003e\u003ccode\u003e@​Omri-Ben-Yair\u003c/code\u003e\u003c/a\u003e\nin \u003ca\nhref\u003d\"https://redirect.github.com/youtype/mypy_boto3_builder/issues/336\"\u003e#336\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[all]\u003c/code\u003e Unions use the same type annotations as the rest\nof the structures due to proper fallbacks\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eFixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e[services]\u003c/code\u003e Universal input/output shapes were not\nreplaced properly in service subresources\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[docs]\u003c/code\u003e Simplified doc links rendering for services\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[services]\u003c/code\u003e Cleaned up unnecessary imports in\n\u003ccode\u003eclient.pyi\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e[builder]\u003c/code\u003e Import records with fallback are always\nrendered\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/blockquote\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003eSee full diff in \u003ca\nhref\u003d\"https://github.com/youtype/mypy_boto3_builder/commits\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003dmypy-boto3-glue\u0026package-manager\u003duv\u0026previous-version\u003d1.43.34\u0026new-version\u003d1.43.37)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\n\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "2c7552324800f40adbeda844bbc40d3420c05a84",
      "tree": "f5638296fd45d606392dea11ba53a42d393c835c",
      "parents": [
        "c109e100193bc6ddf8097ea6e587733d8a33e575"
      ],
      "author": {
        "name": "Anas Khan",
        "email": "anxkhn28@gmail.com",
        "time": "Wed Jul 08 21:38:11 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 08 09:08:11 2026 -0700"
      },
      "message": "fix(ci): correct stale-issue-label and exempt security issues (#3605)\n\n# Rationale for this change\n\nThe stale-bot workflow (`.github/workflows/stale.yml`) configures the\nissue side\nincorrectly:\n\n```yaml\nstale-issue-label: \u0027stale,security\u0027\nexempt-issue-labels: \u0027not-stale\u0027\n```\n\n`stale-issue-label` takes a **single** label and `actions/stale` applies\nit\nverbatim (it is not comma-split, unlike the `*-labels` inputs). So\ninstead of\ntagging stale issues with `stale`, the workflow tags them with one bogus\nlabel\nliterally named `stale,security`. That breaks the workflow\u0027s own\n`stale-issue-message` (which tells users to add `not-stale`, keyed on\nthe stale\nstate) and anything else that relies on a plain `stale` label.\n\nIt also leaves `security` out of `exempt-issue-labels`, so\n`security`-labeled\nissues are still marked stale and auto-closed after 180+14 days. This is\ninconsistent with the **PR** side of the same file, which already\nexempts\n`security`:\n\n```yaml\nstale-pr-label: \u0027stale\u0027\nexempt-pr-labels: \u0027not-stale,security\u0027\n```\n\nThe value was introduced in #3125, which changed `stale-issue-label:\n\u0027stale\u0027` to\n`\u0027stale,security\u0027` in the same change that added\n`exempt-pr-labels: \u0027not-stale,security\u0027`, i.e. `security` was meant as\nan\nexemption on both sides but landed in the wrong key on the issue side.\n\nThis change makes the issue side mirror the (already correct) PR side:\n\n```yaml\nstale-issue-label: \u0027stale\u0027\nexempt-issue-labels: \u0027not-stale,security\u0027\n```\n\n## Are these changes tested?\n\nThere is no test harness for GitHub Actions workflow semantics in this\nrepo, so\nthis was validated by inspection against the pinned action\u0027s contract\nand source:\n\n- Against `actions/stale`\u0027s `action.yml` at the pinned SHA\n(`eb5cf3af3ac0a1aa4c9c45633dd1ae542a27a899`, v10.3.0):\n`stale-issue-label` is\ndocumented as \"The label to apply when an issue is stale\" (single value,\ndefault `Stale`), while `exempt-issue-labels` documents \"Separate\nmultiple\nlabels with commas\". In the action source, the stale label is applied\nverbatim\nand only the exempt labels are comma-split, confirming both effects\nabove.\n- `stale-issue-label: \u0027stale\u0027` matches the PR side of this same file and\nthe\n  Java `apache/iceberg` `stale.yml`.\n- Repo linters pass on the changed file (`check-yaml`, `codespell`,\n  trailing-whitespace, end-of-file-fixer).\n\n## Are there any user-facing changes?\n\nNo. This only affects the repository\u0027s stale-bot automation (issue\nlabeling and\nwhich issues are exempt from auto-close). No changelog label needed."
    },
    {
      "commit": "c109e100193bc6ddf8097ea6e587733d8a33e575",
      "tree": "4297f0ef17526bfcf8f33bdae246e732b2945ed4",
      "parents": [
        "1a87aa3c519839aa3f8713631af6d7ec4bf1d34c"
      ],
      "author": {
        "name": "Jared Yu (余启正)",
        "email": "qzyu999@gmail.com",
        "time": "Wed Jul 08 09:05:27 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Wed Jul 08 09:05:27 2026 -0700"
      },
      "message": "Build: Add .venv/ to .gitignore (#3626)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- Closes #${GITHUB_ISSUE_ID} --\u003e\n\n# Rationale for this change\n\n`.venv/` is the default directory name created by `python -m venv .venv`\nand is the convention recommended by the Python docs and modern tooling\nlike `uv`. Currently `.gitignore` only ignores `venv/` but not `.venv/`,\nso contributors using the dotted convention could accidentally stage\ntheir virtualenv.\n\n## Are these changes tested?\n\nN/A — this is a `.gitignore`-only change.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "1a87aa3c519839aa3f8713631af6d7ec4bf1d34c",
      "tree": "216831c4a71f35c0ecf6ae405933b120441e4ef0",
      "parents": [
        "af1416de9e5206268489558c0067ef61a4bb1147"
      ],
      "author": {
        "name": "Anas Khan",
        "email": "83116240+anxkhn@users.noreply.github.com",
        "time": "Tue Jul 07 01:46:02 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 22:16:02 2026 +0200"
      },
      "message": "fix: require `pyarrow\u003e\u003d18.0.0` for native UUID type support (#3606)\n\n\u003c!-- Closes #1174 --\u003e\n\n# Rationale for this change\n\nPyIceberg\u0027s PyArrow UUID handling depends on the native UUID APIs\n`pyarrow.uuid()`\nand `pyarrow.UuidType`, but the `pyarrow`, `pandas`, `duckdb`, and `ray`\nextras\nstill pin `pyarrow\u003e\u003d17.0.0`.\n\n- On write, `PyArrowSchemaVisitor.visit_uuid` returns `pa.uuid()`\n  (`pyiceberg/io/pyarrow.py:806`).\n- On read, `_ConvertToIceberg.primitive` branches on\n  `isinstance(primitive, pa.UuidType)` (`pyiceberg/io/pyarrow.py:1497`).\n\nBoth `pyarrow.uuid()` and `pyarrow.UuidType` were introduced in Apache\nArrow\n18.0.0 (released 2024-10-28) and do not exist in 17.x. So an environment\nthat\nresolves `pyarrow\u003d\u003d17.x` under the current floor raises\n`AttributeError: module \u0027pyarrow\u0027 has no attribute \u0027uuid\u0027` (or\n`\u0027UuidType\u0027`) as\nsoon as a UUID-typed column is written, or an Arrow schema containing a\nUUID is\nconverted back to Iceberg.\n\nThis usage was added in #2007 (\"Fix UUID support\") without raising the\nfloor, and\nthe earlier `Bump PyArrow to 18.0.0` change only moved the tested/locked\nversion,\nnot the declared lower bound. This PR bumps the floor to\n`pyarrow\u003e\u003d18.0.0` for the\nfour affected extras so the declared dependency matches what the code\nactually\nrequires. See also #1174 (Minimum required pyarrow version).\n\n## Are these changes tested?\n\nThis is a dependency-floor bump with no code change, so the real guard\nis CI\nresolving the raised floor across the supported Python matrix; `uv lock\n--check`\nconfirms `uv.lock` stays in sync with `pyproject.toml`.\n\nLocally:\n- `uv lock --check` passes (lock in sync).\n- `make lint` (ruff, ruff-format, mypy, license, uv-lock, ...) all pass.\n- Existing UUID coverage still passes and exercises both affected code\npaths:\n  `tests/io/test_pyarrow_visitor.py` (60 passed),\n`tests/utils/test_schema_conversion.py -k UUID` (2 passed), and the UUID\ncases in\n  `tests/test_conversions.py` (2 passed). A manual round-trip\n  `UUIDType -\u003e pa.uuid() -\u003e pa.UuidType -\u003e UUIDType` runs clean.\n\nNo new test is added because there is no new code path to cover: the\nexisting UUID\nconversion tests already exercise `visit_uuid` and `_ConvertToIceberg`,\nand the\nfloor bump only makes the declared dependency honest. A heavier\nalternative would\nbe to version-gate `pa.uuid()`/`pa.UuidType` at runtime (as done for\n`AzureFileSystem` via `MIN_PYARROW_VERSION_SUPPORTING_AZURE_FS` in\n`pyiceberg/io/pyarrow.py`), but that keeps UUID unsupported on 17.x\nrather than\nrequiring the version the feature needs; happy to go that route instead\nif\npreferred.\n\n## Are there any user-facing changes?\n\nYes, indirectly: the minimum supported `pyarrow` for the `pyarrow`,\n`pandas`,\n`duckdb`, and `ray` extras rises from 17.0.0 to 18.0.0. This only\naffects\nenvironments currently resolving `pyarrow` 17.x, where UUID columns are\nalready\nbroken; it prevents that unsupported install rather than changing any\nworking\nbehavior. (Adding the `changelog` label if this warrants a changelog\nentry - I\ndon\u0027t have permission to set labels as an external contributor.)"
    },
    {
      "commit": "af1416de9e5206268489558c0067ef61a4bb1147",
      "tree": "0e7f7918c485e5361a3256b30f9e339e001260d4",
      "parents": [
        "9a23d17ce0517f4f503cf4587cc97e1aa175c661"
      ],
      "author": {
        "name": "Jared Yu (余启正)",
        "email": "qzyu999@gmail.com",
        "time": "Mon Jul 06 12:50:05 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 21:50:05 2026 +0200"
      },
      "message": "Docs: Add missing `_downcast_ns_timestamp_to_us` docstring (#3594)\n\n## Which issue does this PR close?\n\nMinor documentation gap (no issue).\n\n## Rationale for this change\n\nThe `ArrowScan` class declares `_downcast_ns_timestamp_to_us: bool |\nNone` as a class-level type annotation and documents all other\nattributes in the docstring, but this attribute was missing from the\nAttributes section.\n\n## What changes are included in this PR?\n\nAdds one line to the `ArrowScan` class docstring documenting the\n`_downcast_ns_timestamp_to_us` attribute.\n\n## Are there any user-facing changes?\n\nNo."
    },
    {
      "commit": "9a23d17ce0517f4f503cf4587cc97e1aa175c661",
      "tree": "c155894a6fb88dbb0af0e86e85478480f9545f51",
      "parents": [
        "9d36e2361493a7f582490519edac848a376ac913"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Mon Jul 06 21:33:54 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jul 06 21:33:54 2026 +0200"
      },
      "message": "Build: Bump actions/setup-python from 6.2.0 to 6.3.0 (#3599)"
    },
    {
      "commit": "9d36e2361493a7f582490519edac848a376ac913",
      "tree": "febedd06091735acfc124058217e9ab34a93a688",
      "parents": [
        "41276a3998e28a2d5832563585beaccab22a3c59"
      ],
      "author": {
        "name": "Fokko Driesprong",
        "email": "fokko@apache.org",
        "time": "Tue Jun 30 06:47:59 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 29 21:47:59 2026 -0700"
      },
      "message": "Bump to Java Iceberg 1.11.0 (#3389)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${GITHUB_ISSUE_ID} --\u003e\n\n# Rationale for this change\n\nThis reverts https://github.com/apache/iceberg-python/pull/3240 and we\nnow should be able to support custom `namespace-seperator`\n\n## Are these changes tested?\n\n## Are there any user-facing changes?\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "41276a3998e28a2d5832563585beaccab22a3c59",
      "tree": "70220c526de9ea81464da729f405b21ba8c16dc7",
      "parents": [
        "71f0f0b55b58073640beb8f16b38b93ea31776ee"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Tue Jun 30 13:02:00 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 06:02:00 2026 +0200"
      },
      "message": "Fix strip spec-mandated DV blob framing before deserializing (#3576)\n\n# Rationale for this change\n\nFix `_payload` storing `puffin[8:]` instead of `puffin` — blob offsets\nin the footer are file-relative (from byte 0), not relative to byte 8.\nThe two bugs cancelled for single-blob files at offset 4; the fix was\nonly testable once PuffinFile supported multi-blob/compressed files.\n\nAlso widen `PuffinBlobMetadata.type` from\n`Literal[\"deletion-vector-v1\"]`\nto `str` so `PuffinFile` can parse files containing non-DV blobs without\na Pydantic validation error.\n\n## Are these changes tested?\n\nYes. Copied files from\nhttps://github.com/apache/iceberg/tree/main/core/src/test/resources/org/apache/iceberg/puffin/v1\n`sample-metric-data-compressed-zstd.bin` will be added separately in\n#3575\n\n## Are there any user-facing changes?\n\nNo\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "71f0f0b55b58073640beb8f16b38b93ea31776ee",
      "tree": "4e3df96d2da4f8816f7b88ec35235dc9c7e2b3e7",
      "parents": [
        "da66a12d7d2dd29c1440c8b47eefa5814701d111"
      ],
      "author": {
        "name": "Fokko Driesprong",
        "email": "fokko@apache.org",
        "time": "Tue Jun 30 05:59:31 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 05:59:31 2026 +0200"
      },
      "message": "CI: Pass args through docker-compose (#3587)\n\n# Rationale for this change\n\nThis way we pass in the MIRROR from docker-compose to the Dockerfile as\nwell. Also git-ignore the `.env` file to avoid checking in this file.\n\n## Are these changes tested?\n\n## Are there any user-facing changes?\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "da66a12d7d2dd29c1440c8b47eefa5814701d111",
      "tree": "3ea54e33b16141bd48a488bbca988270f6878475",
      "parents": [
        "da665337ff9121fa150e0af7884432823d3418e7"
      ],
      "author": {
        "name": "Kevin Liu",
        "email": "kevinjqliu@users.noreply.github.com",
        "time": "Mon Jun 29 23:33:23 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 29 20:33:23 2026 -0700"
      },
      "message": "Prune dependency upper bounds (#3586)\n\nThis PR removes as many upperbounds restrictions as possible from our\ndependencies.\n\nWhy remove unnecessary upper bounds:\n- Makes PyIceberg easier to install alongside applications that already\nuse newer compatible dependency versions.\n- Reduces resolver conflicts and forced downgrades for downstream users,\nwhile keeping caps where there is a real compatibility boundary or known\nbad version.\n\nWe already removed upperbound for pyarrow in #2258\nAnd theres a request to remove upperbound for cachetools in #3214\n\nCloses #3214\n\nChanges:\n- Removes upper bounds that passed local validation, while keeping the\nremaining compatibility caps.\n- Refreshes `uv.lock` with upgraded packages.\n- Updates tests for newer Moto and PyArrow behavior exposed by the\nlockfile refresh.\n\nValidation:\n- `make test PYTHON\u003d3.12` (`3736 passed, 1534 deselected`)"
    },
    {
      "commit": "da665337ff9121fa150e0af7884432823d3418e7",
      "tree": "d84e5873f673ab70b4143597abcfaecc98b67692",
      "parents": [
        "d871cd2de7550eb02dc6c4e0753d846088ccd7c3"
      ],
      "author": {
        "name": "Junwang Zhao",
        "email": "zhjwpku@gmail.com",
        "time": "Tue Jun 30 11:12:59 2026 +0800"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 30 05:12:59 2026 +0200"
      },
      "message": "Reject unsupported identity transform types (#3517)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n# Rationale for this change\n\nPer spec[1], the identity transform source type must be any primitive\nexcept for geometry, geography, and variant. This PR rejects\nGeographyType and GeometryType as source types for identity\ntransforms.(No VariantType yet)\n\n[1] https://iceberg.apache.org/spec/#partition-transforms\n\n## Are these changes tested?\n\nYes\n\n## Are there any user-facing changes?\n\nNo"
    },
    {
      "commit": "d871cd2de7550eb02dc6c4e0753d846088ccd7c3",
      "tree": "6b1d2097747d3062498880810d3f498fd0bf14fa",
      "parents": [
        "de48fe4cedc275e57200832aa2aca1a5597c4b2c"
      ],
      "author": {
        "name": "Kevin Liu",
        "email": "kevinjqliu@users.noreply.github.com",
        "time": "Mon Jun 29 02:59:43 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 23:59:43 2026 -0700"
      },
      "message": "Build: Bump gcsfs to 2026.6.0 (#3582)"
    },
    {
      "commit": "de48fe4cedc275e57200832aa2aca1a5597c4b2c",
      "tree": "38cc007b4c869629573f6bec2d496bbdd11439ae",
      "parents": [
        "f17bdd522d5ff0e9c1353926c3e42d898c5f41d2"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Mon Jun 29 15:11:38 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 23:11:38 2026 -0700"
      },
      "message": "Infra: Set timeout for jobs in python-ci.yml (#3581)\n\n# Rationale for this change\n\nI suggest setting a timeout for CI to allow us to identify unexpected\nslowdown:\n* #3580\n\nEach job takes about:\n* lint-and-unit-test: 3~5 minutes\n* integration-test: ~12 minutes\n* integration-test-s3, integration-test-adls, integration-test-gcs: 1\nminute\n\n## Are these changes tested?\n\nYes\n\n## Are there any user-facing changes?\n\nNo"
    },
    {
      "commit": "f17bdd522d5ff0e9c1353926c3e42d898c5f41d2",
      "tree": "d4d84417d7acb3efb05fa6194b72d48236e18f73",
      "parents": [
        "e405573cfdaf7a23a1fc84882e6aafa019591337"
      ],
      "author": {
        "name": "Kevin Liu",
        "email": "kevinjqliu@users.noreply.github.com",
        "time": "Mon Jun 29 00:55:36 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 21:55:36 2026 -0700"
      },
      "message": "Revert \"Build: Bump gcsfs from 2026.5.0 to 2026.6.0\" (#3580)\n\nReverts apache/iceberg-python#3560\n\nDependency bump is causing `integration-test-gcs` to be really slow 54m\nvs previous 1m\n\nhttps://github.com/apache/iceberg-python/pull/3560#issuecomment-4829027697"
    },
    {
      "commit": "e405573cfdaf7a23a1fc84882e6aafa019591337",
      "tree": "73bec2656a7b05624553bcef1b2f9f95b41898fa",
      "parents": [
        "09db25bb0003fd1751ff592d510cb60b6cd16e1c"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Mon Jun 29 13:39:59 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 21:39:59 2026 -0700"
      },
      "message": "Rename _scan_plan_helper method to _plan_manifest_entries (#3579)\n\n# Rationale for this change\n\nThe method name should describe what it does. \n\n- Follow-up of https://github.com/apache/iceberg-python/pull/3553\n\n## Are these changes tested?\n\nYes\n\n## Are there any user-facing changes?\n\nNo, this is an internal method."
    },
    {
      "commit": "09db25bb0003fd1751ff592d510cb60b6cd16e1c",
      "tree": "43cbbb0d80f016faeb6220286dfafa83e5ce5767",
      "parents": [
        "6c3c2f351f1797fba736c3ad3bd72e90d4932849"
      ],
      "author": {
        "name": "Kristofer Gaudel",
        "email": "68076186+kris-gaudel@users.noreply.github.com",
        "time": "Sun Jun 28 23:36:51 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 21:36:51 2026 -0700"
      },
      "message": "Make manifest cache size configurable (#2993)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${2952} --\u003e\n\nCloses #2952\n\n# Rationale for this change\nThrough discussion in issue #2325, we realized that there was a memory\nleak in the manifest cache. PR\nhttps://github.com/apache/iceberg-python/pull/2951 fixed this memory\nleak, but we decided that it would be best for developer experience if\nusers could configure the cache for their needs.\n\nThis includes the ability to configure the manifest cache size,\nincluding setting it to `0` to disable caching.\n\n## Are these changes tested?\nYes - unit tests are included to verify these changes\n\n## Are there any user-facing changes?\nYes:\n- `manifest-cache-size` can be used in `.pyiceberg.yaml` to configure\nthe size of the manifest cache\n- `PYICEBERG_MANIFEST_CACHE_SIZE` can be used to configure the size of\nthe manifest cache\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e\n\n---------\n\nCo-authored-by: Kevin Liu \u003ckevin.jq.liu@gmail.com\u003e"
    },
    {
      "commit": "6c3c2f351f1797fba736c3ad3bd72e90d4932849",
      "tree": "d1d1bda9845f3d8b0353b3ff01721670cf4ef7f6",
      "parents": [
        "5be1595530ad2edcbdf0540103ef49eface35f99"
      ],
      "author": {
        "name": "Tanmay Rauth",
        "email": "t_rauth@apple.com",
        "time": "Sun Jun 28 12:40:17 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 21:40:17 2026 +0200"
      },
      "message": "Make `scan_plan_helper` private (#3541) (#3553)\n\nscan_plan_helper is an internal helper for local scan planning, not a\npublic extension point. Rename it to _scan_plan_helper to reflect its\nintended visibility and update its only caller in inspect.py.\n\nThe method was introduced recently in d99936a and has not been part of\nany released public API, so no deprecation shim is required.\nFixes: #3541\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${GITHUB_ISSUE_ID} --\u003e\n\n# Rationale for this change\n\n## Are these changes tested?\n\n## Are there any user-facing changes?\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "5be1595530ad2edcbdf0540103ef49eface35f99",
      "tree": "5a07b616f1a805355515481b7b2422fca0d74bc1",
      "parents": [
        "9ba64ab8637ee63524b29de71ecffb94795dae16"
      ],
      "author": {
        "name": "Sreesh Maheshwar",
        "email": "maheshwarsreesh@gmail.com",
        "time": "Sun Jun 28 20:35:37 2026 +0100"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 12:35:37 2026 -0700"
      },
      "message": "Feature: Incremental Append Scan (#3512)\n\n\u003c!-- Closes #2634 --\u003e\n\nCloses #2634.\n\n# Rationale for this change\n\nAdds `IncrementalAppendScan`, which reads the data appended between two\nsnapshots — the building block for incremental ingestion. Largely a\nrevival of the work in #2235; see #2634 and the previous PRs for\nmotivation.\n\nSplit out of #3364 at the reviewers\u0027 request, and builds on the\nnow-merged `BaseScan` / `ManifestGroupPlanner` refactor (#3511), so this\nPR\u0027s diff is the append-scan feature alone.\n\nThe surface mirrors Iceberg-Java\u0027s engine-facing API (snapshot IDs,\ninclusive/exclusive start, optional start) rather than the narrower\nSpark read options, since PyIceberg is increasingly used by engines\n(e.g. Polars). See the API discussion on this PR.\n\nReferences: https://github.com/apache/iceberg (Iceberg-Java and Spark)\nand https://github.com/apache/iceberg-cpp/pull/590. Inline review-aid\ncomments (prefixed `[AI reviewer aid]`) point at the relevant reference\ncode.\n\n# API\n\n`Table.incremental_append_scan(...)` returns an `IncrementalAppendScan`;\n`StagedTable` overrides it to raise, mirroring `scan()`. The scan reads\nthe rows added by **append** snapshots in `(from, to]`, projected onto\nthe table\u0027s current schema; delete / overwrite / replace snapshots in\nthe range (e.g. compaction) are ignored.\n\nThe range is set via the factory\u0027s Spark-style kwargs or the builder\nmethods, each of which returns a refined copy (like `select()` /\n`filter()`):\n\n```python\ntable.incremental_append_scan(\n    from_snapshot_id_exclusive\u003dNone,   # optional; defaults to the oldest ancestor of `to`\n    to_snapshot_id_inclusive\u003dNone,     # optional; defaults to the current snapshot\n    row_filter\u003d..., selected_fields\u003d..., case_sensitive\u003d..., options\u003d..., limit\u003d...,\n)\n\nscan.from_snapshot_id_exclusive(id)    # or .from_snapshot_id_inclusive(id)\n    .to_snapshot_id_inclusive(id)\n```\n\nThe range is held as public attributes — `from_snapshot_id` +\n`from_snapshot_inclusive` + `to_snapshot_id` — a single start slot plus\nan inclusive flag, mirroring Java\u0027s `TableScanContext` and consistent\nwith the other scans.\n\n# Changes\n\n- Range resolution mirrors Java\u0027s `BaseIncrementalScan`: an unset start\nscans from the oldest ancestor of the end; an inclusive start resolves\nto its parent as the exclusive boundary; an exclusive start is validated\nwith `is_parent_ancestor_of`, so an expired start cursor is accepted as\nlong as the lineage still passes through it; the end defaults to the\ncurrent snapshot; an empty table with no range set scans nothing.\n- Planning walks the append-only ancestors in the range, dedups the data\nmanifests whose `added_snapshot_id` is in range (set semantics via\n`ManifestFile.__eq__` / `__hash__`), and filters manifest entries to\n`ADDED`-in-range via a new `manifest_entry_filter` on\n`ManifestGroupPlanner.plan_files`. Compacted (`rewrite_data_files`)\noutput is therefore not picked up — no double counting.\n- Projects onto the table\u0027s **current** schema (matching Java/C++), so\nrows written under an older schema in the range get `NULL` for newer\ncolumns.\n- Adds snapshot helpers `ancestors_between_ids`, `is_ancestor_of`, and\n`is_parent_ancestor_of`.\n- Arrow materialization (`to_arrow` / `to_arrow_batch_reader`) is shared\nwith `DataScan` via small module-level helpers that take the projected\nschema explicitly, so `BaseScan` stays projection-free (per the #3511\nreview).\n\n# Out of scope (tracked follow-ups)\n\n- Branch selection (`use_branch`) and per-endpoint ref/tag start \u0026 end\n(`from_ref_*` / `to_ref_*`) — the rest of the engine-facing surface Java\nexposes.\n- `count()`, REST server-side planning, and user-facing doc examples\n(`mkdocs`).\n- `dictionary_columns` on `IncrementalAppendScan.to_arrow` /\n`to_arrow_batch_reader` (added to `DataScan` in #3461; the shared\nhelpers already thread it) — kept out to isolate this PR.\n\n# Are these changes tested?\n\nYes — unit tests (range resolution including unset / inclusive /\nexclusive and expired start, current-schema projection, builder and\n`update()` copies, empty table, staged-table guard) and integration\ntests (append-only, non-append snapshots ignored, compaction not\ndouble-counted, schema evolution within range, partition- and\nmetrics-evaluator pruning, disconnected snapshots), plus the\n`test_incremental_read` provision fixture.\n\n# Are there any user-facing changes?\n\nYes — the new `Table.incremental_append_scan(...)` API and\n`IncrementalAppendScan` class. No changes to existing public surface.\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "9ba64ab8637ee63524b29de71ecffb94795dae16",
      "tree": "9c5013203e0e4c5949852164aabc734ad5c34242",
      "parents": [
        "2b1be37e1f61ed077ff89fb8b5147a258b1c0559"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:31:43 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:31:43 2026 +0200"
      },
      "message": "Build: Bump mkdocstrings-python from 2.0.4 to 2.0.5 (#3567)"
    },
    {
      "commit": "2b1be37e1f61ed077ff89fb8b5147a258b1c0559",
      "tree": "0c7d75f9d544bce34a60f1fd09106709e6bc4a9a",
      "parents": [
        "043bc4e171defccfbcd671239beab33735041382"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Mon Jun 29 03:31:05 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:31:05 2026 +0200"
      },
      "message": "Build: Bump pyarrow from 23.0.1 to 24.0.0 (#3538)\n\n# Rationale for this change\n\n- Closes #3531\n- Closes #3538\n\n## Are these changes tested?\n\nYes\n\n## Are there any user-facing changes?\n\nNo\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "043bc4e171defccfbcd671239beab33735041382",
      "tree": "cf17a7202def4e82f2bba25e0d95a1e4a1b3e3cf",
      "parents": [
        "fe91c0b34c65837fd7d12b498ff8ac11c016f3ca"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:29:38 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:29:38 2026 +0200"
      },
      "message": "Build: Bump sqlalchemy from 2.0.50 to 2.0.51 (#3565)"
    },
    {
      "commit": "fe91c0b34c65837fd7d12b498ff8ac11c016f3ca",
      "tree": "664c8596b223e9b57343254a1133a0d569c5a701",
      "parents": [
        "bc1fc51ba982068bccace237a9e4ca884956bff7"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:29:11 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:29:11 2026 +0200"
      },
      "message": "Build: Bump duckdb from 1.5.3 to 1.5.4 (#3564)"
    },
    {
      "commit": "bc1fc51ba982068bccace237a9e4ca884956bff7",
      "tree": "f50312a2b7737baea1a157df4f3e7b723b213b41",
      "parents": [
        "892744ab3c9c759cfb5109921ecb1e7368d7bb1e"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:28:56 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:28:56 2026 +0200"
      },
      "message": "Build: Bump actions/upload-artifact/merge from 4.6.2 to 7.0.1 (#3561)"
    },
    {
      "commit": "892744ab3c9c759cfb5109921ecb1e7368d7bb1e",
      "tree": "a6524682f644bc0f8f6eb00fb2a041ce858c58c1",
      "parents": [
        "e7681cd9635281bc25f05b920d2f0f386278daf3"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:28:28 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:28:28 2026 +0200"
      },
      "message": "Build: Bump joserfc from 1.6.3 to 1.6.7 (#3573)"
    },
    {
      "commit": "e7681cd9635281bc25f05b920d2f0f386278daf3",
      "tree": "44e01159143c5c7dc716cd1dfca2cb45b29f6d76",
      "parents": [
        "4951db93525ffa8d0761d1058ca15fc2010e2069"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:25:42 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:25:42 2026 +0200"
      },
      "message": "Build: Bump huggingface-hub from 1.18.0 to 1.20.1 (#3562)"
    },
    {
      "commit": "4951db93525ffa8d0761d1058ca15fc2010e2069",
      "tree": "9060d75466840dfd1a83ed314e510678f9872715",
      "parents": [
        "930d0fa05f5cf81f44822035f83c0373b2fb7d96"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:25:17 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:25:17 2026 +0200"
      },
      "message": "Build: Bump msgpack from 1.1.2 to 1.2.1 (#3544)"
    },
    {
      "commit": "930d0fa05f5cf81f44822035f83c0373b2fb7d96",
      "tree": "3cf8dc0f322aeeba439c5c87bed4ec19011439a0",
      "parents": [
        "4047ef6a522563de2387f3e95c6b927b0673784d"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:21:45 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:21:45 2026 +0200"
      },
      "message": "Build: Bump google-cloud-bigquery from 3.41.0 to 3.42.0 (#3558)"
    },
    {
      "commit": "4047ef6a522563de2387f3e95c6b927b0673784d",
      "tree": "6f3f82bc02489ed85960fe2219e562a4c8a7a4dd",
      "parents": [
        "8337711b7a9f70266ab2b35d258a89a258146cc0"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:20:01 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:20:01 2026 +0200"
      },
      "message": "Build: Bump gcsfs from 2026.5.0 to 2026.6.0 (#3560)"
    },
    {
      "commit": "8337711b7a9f70266ab2b35d258a89a258146cc0",
      "tree": "3afb001955cb9d48bdec037f33a06bd5001d7d5d",
      "parents": [
        "6dc83e8938a3abe09429f4a4b27b11a63f88c6c4"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:18:39 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:18:39 2026 +0200"
      },
      "message": "Build: Bump actions/checkout from 6.0.3 to 7.0.0 (#3559)"
    },
    {
      "commit": "6dc83e8938a3abe09429f4a4b27b11a63f88c6c4",
      "tree": "fa6b33489cbc6a37392ce8b41010e85ab80848a7",
      "parents": [
        "45593e4d88be85d7c37827d85fcf19904bba548f"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:18:02 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:18:02 2026 +0200"
      },
      "message": "Build: Bump ipykernel from 7.2.0 to 7.3.0 (#3536)"
    },
    {
      "commit": "45593e4d88be85d7c37827d85fcf19904bba548f",
      "tree": "d4124ffd1450563989ac6919c571455fb2faaabf",
      "parents": [
        "7974fe121673fbb1425203405cb7399db1046c17"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:16:56 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:16:56 2026 +0200"
      },
      "message": "Build: Bump pypa/cibuildwheel from 3.4.1 to 4.1.0 (#3532)"
    },
    {
      "commit": "7974fe121673fbb1425203405cb7399db1046c17",
      "tree": "ed043bc3784d5de93aab640c8ad60f0eb4389a65",
      "parents": [
        "9d4cefb6adefe4894490288a913b292562df1539"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 28 20:16:17 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 28 20:16:17 2026 +0200"
      },
      "message": "Build: Bump bleach from 6.3.0 to 6.4.0 (#3518)"
    },
    {
      "commit": "9d4cefb6adefe4894490288a913b292562df1539",
      "tree": "598ae3ced1037a320bf35292e994bba08a32d1af",
      "parents": [
        "aba210a723a89d1f8e0bcfb05d993009258ae539"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jun 27 22:17:46 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 27 22:17:46 2026 -0700"
      },
      "message": "Build: Bump jupyterlab from 4.5.8 to 4.6.0 (#3568)"
    },
    {
      "commit": "aba210a723a89d1f8e0bcfb05d993009258ae539",
      "tree": "f52d32487b6d9ea573cf5bd060149b9f75044285",
      "parents": [
        "e36f1a6386c5e2017c33048e62e627ca0e0b6942"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jun 27 14:05:23 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 27 14:05:23 2026 -0700"
      },
      "message": "Build: Bump mypy-boto3-glue from 1.43.23 to 1.43.34 (#3569)"
    },
    {
      "commit": "e36f1a6386c5e2017c33048e62e627ca0e0b6942",
      "tree": "f7d923f33690c7c4166a27043fcf6893e6f8b564",
      "parents": [
        "f9424df5fdec4457332f40478ad61ce0c8dcfa3a"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jun 27 14:05:00 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 27 14:05:00 2026 -0700"
      },
      "message": "Build: Bump pytest from 9.0.3 to 9.1.1 (#3570)"
    },
    {
      "commit": "f9424df5fdec4457332f40478ad61ce0c8dcfa3a",
      "tree": "0e95953103228e665400560f540b33a0feee9ccc",
      "parents": [
        "3b67ad28848ee02b2223f87e9a8c6b6e7254c502"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jun 27 14:04:32 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 27 14:04:32 2026 -0700"
      },
      "message": "Build: Bump griffe from 2.0.2 to 2.1.0 (#3571)"
    },
    {
      "commit": "3b67ad28848ee02b2223f87e9a8c6b6e7254c502",
      "tree": "2d0ba7abd303bdb38f38e064e588cd6a3df3fb2e",
      "parents": [
        "1bdea24d876a8a2cd4ac7773b30658628a710c60"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jun 27 14:04:11 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 27 14:04:11 2026 -0700"
      },
      "message": "Build: Bump prek from 0.4.4 to 0.4.5 (#3572)"
    },
    {
      "commit": "1bdea24d876a8a2cd4ac7773b30658628a710c60",
      "tree": "9735ba8dc97d44d5a08a098b4b3b470dc5b01fc6",
      "parents": [
        "01a86f987d1924ca3246a2b985b78890ec0c0fbd"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sat Jun 27 14:03:43 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 27 14:03:43 2026 -0700"
      },
      "message": "Build: Bump google-auth from 2.53.0 to 2.55.0 (#3563)"
    },
    {
      "commit": "01a86f987d1924ca3246a2b985b78890ec0c0fbd",
      "tree": "62ce75023fe9aeb2691534534302e04a2229f401",
      "parents": [
        "b8ffdd3059ce5c19b37ac2e5b9918d2fab93f72c"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Thu Jun 25 22:32:06 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 25 09:32:06 2026 -0400"
      },
      "message": "Extract DeletionVector logic from PuffinFile (#3491)\n\n# Rationale for this change\n\nPuffinFile handles two tasks: format parsing (magic bytes, footer,\nblobs) and deletion vector domain logic (bitmap deserialization and\nPyArrow conversion).\nThis will become problematic when we introduce support for the NDV\n`apache-datasketches-theta-v1` blob in the future.\n\n## Are these changes tested?\n\nYes\n\n## Are there any user-facing changes?\n\nYes - PuffinFile class user needs to call DeletionVector."
    },
    {
      "commit": "b8ffdd3059ce5c19b37ac2e5b9918d2fab93f72c",
      "tree": "79a087447cf4be7b08cbe749226f112ee17496e5",
      "parents": [
        "c85c9eecb1b79cdc0acd4dc27983802788518aa3"
      ],
      "author": {
        "name": "vishnu prakash",
        "email": "nvishnuprakash02@gmail.com",
        "time": "Wed Jun 24 01:18:24 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 23 15:48:24 2026 -0400"
      },
      "message": "fix(datetime): raise specific \"Missing zone offset\" error in  timestamptz_to_nanos (#3505)\n\n# Rationale for this change\n\n  `timestamptz_to_nanos` should raise a clear \"Missing zone\n  offset\" error when it\u0027s given a nanosecond timestamp that has no\n  timezone. Today it can\u0027t: the check meant to detect a zone-less\n  timestamp accidentally tests the *same* pattern as the success\n  check right above it, so it never matches. The input falls\n  through to the vague \"Invalid timestamp with zone\" error\n  instead.\n\n  The fix is one line check the zone-less pattern\n  (`ISO_TIMESTAMP_NANO`) instead, mirroring \n  `timestamptz_to_micros`, which already does this correctly.\n  (Introduced in #1632.)\n\n  ## Are these changes tested?\n\n  Yes added tests covering the error messages for both\n  `timestamptz_to_nanos` and `timestamp_to_nanos`.\n  \n  ## Are there any user-facing changes?\n\n  Only a clearer error message: a zone-less nanosecond timestamp\n  now reports \"Missing zone offset\" instead of \"Invalid timestamp\n  with zone\". No API changes."
    },
    {
      "commit": "c85c9eecb1b79cdc0acd4dc27983802788518aa3",
      "tree": "d624fc88ab084aeaae32e21fb265a025d721bc53",
      "parents": [
        "8c7912fe61fb73e722d4e8b354763fcc29683a60"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Tue Jun 23 06:14:32 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Mon Jun 22 14:14:32 2026 -0700"
      },
      "message": "CI: Check ASF action allowlist on every PR (#3550)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\n\u003c!-- Closes #${GITHUB_ISSUE_ID} --\u003e\n\n# Rationale for this change\n\n* https://github.com/apache/iceberg/issues/16934\n* https://github.com/apache/iceberg/pull/16926\n\n## Are these changes tested?\n\nN/A\n\n## Are there any user-facing changes?\n\nNo\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "8c7912fe61fb73e722d4e8b354763fcc29683a60",
      "tree": "1c02e0a44005ecc94ad848d4983fcef4a2e19ad6",
      "parents": [
        "d0a9b91eb59a5bef8a7d1603cd20ae7a4fc33895"
      ],
      "author": {
        "name": "Kevin Liu",
        "email": "kevinjqliu@users.noreply.github.com",
        "time": "Mon Jun 22 02:59:11 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 23:59:11 2026 -0700"
      },
      "message": "Add strict NotEqualTo/NotIn null and NaN tests (#3547)"
    },
    {
      "commit": "d0a9b91eb59a5bef8a7d1603cd20ae7a4fc33895",
      "tree": "1802de1b0bde036692174a0f6b098e4de60e71ae",
      "parents": [
        "c66d8b5f6c122d3bdedbad1a39d4ef213e19d50d"
      ],
      "author": {
        "name": "Tanmay Rauth",
        "email": "tanmayrauth@gmail.com",
        "time": "Sun Jun 21 21:10:07 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 21:10:07 2026 -0700"
      },
      "message": "Fix strict NotEqualTo/NotIn pruning with partial nulls or NaNs (#3521)\n\n## Summary\n\nRelated to #3498\n\nFix strict metrics evaluation for `NotEqualTo` and `NotIn` so files are\nonly proven to match when a column contains only nulls or only NaNs.\nMixed null/NaN files now continue through the existing bounds checks\ninstead of being treated as `ROWS_MUST_MATCH`.\n\n## Root Cause\n\nThe strict evaluator used `_can_contain_nulls` / `_can_contain_nans` for\nnegative predicates. That is too broad: a file with values like `[null,\n5]` and bounds `5..5` cannot be proven to match `x !\u003d 5` or `x not in\n{5}` because the non-null row may still fail the predicate.\n\n## Java Parity\n\nThis matches Java\u0027s `StrictMetricsEvaluator`, which only short-circuits\nnegative predicates when the column contains only nulls or only NaNs:\n\n-\n[`notEq`](https://github.com/apache/iceberg/blob/0b30919372df34afb632f037df88c05cdba0b134/api/src/main/java/org/apache/iceberg/expressions/StrictMetricsEvaluator.java#L341-L375)\n-\n[`notIn`](https://github.com/apache/iceberg/blob/0b30919372df34afb632f037df88c05cdba0b134/api/src/main/java/org/apache/iceberg/expressions/StrictMetricsEvaluator.java#L418-L462)\n\n## Validation\n\n- `UV_CACHE_DIR\u003d.cache/uv PYTHON_GIL\u003d1 PYTHONPATH\u003d. uv run pytest\ntests/expressions/test_evaluator.py -k \"mixed_nulls_and_matching_bounds\nor mixed_nans_and_matching_bounds or all_nulls or all_nans or\nstrict_integer_not_in\"`\n- `UV_CACHE_DIR\u003d.cache/uv PYTHON_GIL\u003d1 PYTHONPATH\u003d. uv run pytest\ntests/expressions/test_evaluator.py`\n- `UV_CACHE_DIR\u003d.cache/uv PYTHON_GIL\u003d1 PYTHONPATH\u003d. uv run ruff check\npyiceberg/expressions/visitors.py tests/expressions/test_evaluator.py`\n- `git diff --check`\n\n---------\n\nCo-authored-by: Kevin Liu \u003ckevinjqliu@users.noreply.github.com\u003e"
    },
    {
      "commit": "c66d8b5f6c122d3bdedbad1a39d4ef213e19d50d",
      "tree": "7f24dc32829cf0731300e7e0f46350d620b88f6d",
      "parents": [
        "df71d2ae60e52c191eb85ff87931d7a0801c597c"
      ],
      "author": {
        "name": "Sidra",
        "email": "sidrasaqlain11@gmail.com",
        "time": "Mon Jun 22 05:50:38 2026 +0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 17:50:38 2026 -0700"
      },
      "message": "docs: clean OSS and COS configuration tables (#3452)\n\n## summary\nfixed formatting issues in OSS and Tencent COS configuration\ndocumentation\n\n## changes\n- fixed broken markdown table alignment in OSS section\n- cleaned and standardized OSS configuration table\n- separated Tencent COS into its own properly formatted section\n- ensured all configuration keys remain unchanged\n- improved readability of documentation\n\n## testing\n- pre-commit checks passed\n- markdown linting passed\n- documentation-only change (no code behavior impact)"
    },
    {
      "commit": "df71d2ae60e52c191eb85ff87931d7a0801c597c",
      "tree": "b26aa3b731c4c008a68f6ee2ea0b40d58ecf0319",
      "parents": [
        "fb96df117677a47cf75e8e86f7b88bf47dc0e674"
      ],
      "author": {
        "name": "GayathriSrividya",
        "email": "gayathrirajavarapu7@gmail.com",
        "time": "Mon Jun 22 05:55:05 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 17:25:05 2026 -0700"
      },
      "message": "Fix duplicate filtering path in Arrow task batches (#3448)\n\nCloses #3272\n\n## What this changes\n\nThis PR updates the Arrow scan path in `_task_to_record_batches` to\navoid redundant filtering when there are no positional deletes.\n\n- Keeps predicate pushdown in `Scanner.from_fragment` as the only filter\npath when `positional_deletes` is absent.\n- Applies `current_batch.filter(pyarrow_filter)` only in the\npositional-delete path, after deletes are applied.\n- Preserves empty-batch handling after both delete application and\nconditional filtering.\n\n## Why\n\nThe previous flow could perform an extra table-level refilter even when\nthe scanner already applied the predicate. This change removes that\nstale workaround path while keeping correct behavior for positional\ndelete scenarios.\n\n## Tests\n\nAdded regression coverage in `tests/io/test_pyarrow.py`:\n\n-\n`test_task_to_record_batches_filter_without_positional_deletes_avoids_table_refilter`\n-\n`test_task_to_record_batches_filter_with_positional_deletes_handles_empty_batch`\n\nValidated locally:\n\n- `python -m pytest tests/io/test_pyarrow.py -q -k\n\"task_to_record_batches_nanos or\nfilter_without_positional_deletes_avoids_table_refilter or\nfilter_with_positional_deletes_handles_empty_batch\"`\n- `make lint`\n\n---------\n\nCo-authored-by: Gayathri Srividya Rajavarapu \u003cgayathrir@Gayathris-MacBook-Air.local\u003e\nCo-authored-by: Claude Sonnet 4.6 \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Fokko Driesprong \u003cfokko@apache.org\u003e"
    },
    {
      "commit": "fb96df117677a47cf75e8e86f7b88bf47dc0e674",
      "tree": "79ee18b27369008774d7e2ae5b898d1375decb00",
      "parents": [
        "7fff821199bfc111c9b8b1667b80c846d260c6c5"
      ],
      "author": {
        "name": "Kevin Liu",
        "email": "kevinjqliu@users.noreply.github.com",
        "time": "Sun Jun 21 19:47:43 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 16:47:43 2026 -0700"
      },
      "message": "Return bounds sentinels for long date literals (#3546)"
    },
    {
      "commit": "7fff821199bfc111c9b8b1667b80c846d260c6c5",
      "tree": "d74cf7082001dacca708aff5c042753fa9176e5f",
      "parents": [
        "43b27e4f59c7d25210c5cf1d95c09ccaba14f15a"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Mon Jun 22 06:24:33 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 14:24:33 2026 -0700"
      },
      "message": "Fix string-based `starts_with` and `not_starts_with` methods (#3501)\n\n# Rationale for this change\n\n- Fixes #3497\n\n## Are these changes tested?\n\nYes, the added test fails if we revert this PR\u0027s change. \n\n## Are there any user-facing changes?\n\nYes, this PR fixes a correctness issue. \n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e"
    },
    {
      "commit": "43b27e4f59c7d25210c5cf1d95c09ccaba14f15a",
      "tree": "e38c5ee4e46d532ccb890539962ea71c9680813a",
      "parents": [
        "58969e620b056a8c2dcfecd331689e6d965e7126"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Mon Jun 22 06:14:10 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 14:14:10 2026 -0700"
      },
      "message": "Return overflow sentinel in LongLiteral.to(FloatType) (#3502)\n\n# Rationale for this change\n\n- Fixes #3494\n\n## Are these changes tested?\n\nYes, added assertions fail if we revert this PR\u0027s change.\n\n## Are there any user-facing changes?\n\nYes, users receive an overflow sentinel instead of OverflowError. \n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e\n\n---------\n\nCo-authored-by: Kevin Liu \u003ckevinjqliu@users.noreply.github.com\u003e"
    },
    {
      "commit": "58969e620b056a8c2dcfecd331689e6d965e7126",
      "tree": "0288061b6e54126fb051e466c2c0c6da0759fc4a",
      "parents": [
        "b9185ec1d031005c03f944c9bece6e3a5a725116"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Sun Jun 21 13:49:23 2026 -0700"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 13:49:23 2026 -0700"
      },
      "message": "Build: Bump jupyter-server from 2.18.0 to 2.20.0 (#3539)\n\nBumps [jupyter-server](https://github.com/jupyter-server/jupyter_server)\nfrom 2.18.0 to 2.20.0.\n\u003cdetails\u003e\n\u003csummary\u003eRelease notes\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/releases\"\u003ejupyter-server\u0027s\nreleases\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003ev2.20.0\u003c/h2\u003e\n\u003ch2\u003e2.20.0\u003c/h2\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/compare/v2.19.0...333e700119ee0bcc0b5fcd4c158213d7c275c778\"\u003eFull\nChangelog\u003c/a\u003e)\u003c/p\u003e\n\u003ch3\u003eSecurity fixes\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eCVE-2026-44727 \u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/security/advisories/GHSA-fcw5-x6j4-ccmp\"\u003eGHSA-fcw5-x6j4-ccmp\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eEnhancements made\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix confusing terminal output when using ServerApp.ip\u003d0.0.0.0 \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1643\"\u003e#1643\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/minrk\"\u003e\u003ccode\u003e@​minrk\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdd a toggle to enable curve encryption for all kernels that support\nit \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1638\"\u003e#1638\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e,\n\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/ianthomas23\"\u003e\u003ccode\u003e@​ianthomas23\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/minrk\"\u003e\u003ccode\u003e@​minrk\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBugs fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eGrab the port from \u003ccode\u003ebind_sockets\u003c/code\u003e in case its different\n\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1651\"\u003e#1651\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/choldgraf\"\u003e\u003ccode\u003e@​choldgraf\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eMaintenance and upkeep improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix \u003ccode\u003etest_authorizer\u003c/code\u003e having a spurious comma in params\n\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1664\"\u003e#1664\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdd a reminder to merge GHSA before release \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1659\"\u003e#1659\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eExclude problematic \u003ccode\u003epywinpty\u003c/code\u003e 3.0.4 version \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1658\"\u003e#1658\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eci: explicitly pass base-setup inputs to fix strict validation\nfailures \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1626\"\u003e#1626\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/Copilot\"\u003e\u003ccode\u003e@​Copilot\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eDocumentation improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAlign docs for curve encryption with latest JEP version \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1660\"\u003e#1660\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e,\n\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eRemove PGP key from docs \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1653\"\u003e#1653\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eContributors to this release\u003c/h3\u003e\n\u003cp\u003eThe following people contributed discussions, new ideas, code and\ndocumentation contributions, and review.\nSee \u003ca\nhref\u003d\"https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports\"\u003eour\ndefinition of contributors\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/graphs/contributors?from\u003d2026-05-29\u0026amp;to\u003d2026-06-17\u0026amp;type\u003dc\"\u003eGitHub\ncontributors page for this release\u003c/a\u003e)\u003c/p\u003e\n\u003cp\u003e\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3ACarreau+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/choldgraf\"\u003e\u003ccode\u003e@​choldgraf\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Acholdgraf+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/Copilot\"\u003e\u003ccode\u003e@​Copilot\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3ACopilot+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca\nhref\u003d\"https://github.com/ianthomas23\"\u003e\u003ccode\u003e@​ianthomas23\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Aianthomas23+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Akrassowski+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/minrk\"\u003e\u003ccode\u003e@​minrk\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Aminrk+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3AYann-P+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\u003c/p\u003e\n\u003ch2\u003ev2.19.0\u003c/h2\u003e\n\u003ch2\u003e2.19.0\u003c/h2\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/compare/v2.18.2...664e2255c71efe963f397b9f803dbcf503b5a920\"\u003eFull\nChangelog\u003c/a\u003e)\u003c/p\u003e\n\u003ch3\u003eEnhancements made\u003c/h3\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eChangelog\u003c/summary\u003e\n\u003cp\u003e\u003cem\u003eSourced from \u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/blob/main/CHANGELOG.md\"\u003ejupyter-server\u0027s\nchangelog\u003c/a\u003e.\u003c/em\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003ch2\u003e2.20.0\u003c/h2\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/compare/v2.19.0...333e700119ee0bcc0b5fcd4c158213d7c275c778\"\u003eFull\nChangelog\u003c/a\u003e)\u003c/p\u003e\n\u003ch3\u003eEnhancements made\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix confusing terminal output when using ServerApp.ip\u003d0.0.0.0 \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1643\"\u003e#1643\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/minrk\"\u003e\u003ccode\u003e@​minrk\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdd a toggle to enable curve encryption for all kernels that support\nit \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1638\"\u003e#1638\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e,\n\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/ianthomas23\"\u003e\u003ccode\u003e@​ianthomas23\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/minrk\"\u003e\u003ccode\u003e@​minrk\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBugs fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eGrab the port from \u003ccode\u003ebind_sockets\u003c/code\u003e in case its different\n\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1651\"\u003e#1651\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/choldgraf\"\u003e\u003ccode\u003e@​choldgraf\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eMaintenance and upkeep improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eFix \u003ccode\u003etest_authorizer\u003c/code\u003e having a spurious comma in params\n\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1664\"\u003e#1664\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdd a reminder to merge GHSA before release \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1659\"\u003e#1659\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eExclude problematic \u003ccode\u003epywinpty\u003c/code\u003e 3.0.4 version \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1658\"\u003e#1658\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eci: explicitly pass base-setup inputs to fix strict validation\nfailures \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1626\"\u003e#1626\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/Copilot\"\u003e\u003ccode\u003e@​Copilot\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eDocumentation improvements\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eAlign docs for curve encryption with latest JEP version \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1660\"\u003e#1660\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e,\n\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eRemove PGP key from docs \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1653\"\u003e#1653\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eContributors to this release\u003c/h3\u003e\n\u003cp\u003eThe following people contributed discussions, new ideas, code and\ndocumentation contributions, and review.\nSee \u003ca\nhref\u003d\"https://github-activity.readthedocs.io/en/latest/use/#how-does-this-tool-define-contributions-in-the-reports\"\u003eour\ndefinition of contributors\u003c/a\u003e.\u003c/p\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/graphs/contributors?from\u003d2026-05-29\u0026amp;to\u003d2026-06-17\u0026amp;type\u003dc\"\u003eGitHub\ncontributors page for this release\u003c/a\u003e)\u003c/p\u003e\n\u003cp\u003e\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3ACarreau+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/choldgraf\"\u003e\u003ccode\u003e@​choldgraf\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Acholdgraf+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/Copilot\"\u003e\u003ccode\u003e@​Copilot\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3ACopilot+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca\nhref\u003d\"https://github.com/ianthomas23\"\u003e\u003ccode\u003e@​ianthomas23\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Aianthomas23+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e\n(\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Akrassowski+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/minrk\"\u003e\u003ccode\u003e@​minrk\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3Aminrk+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\n| \u003ca href\u003d\"https://github.com/Yann-P\"\u003e\u003ccode\u003e@​Yann-P\u003c/code\u003e\u003c/a\u003e (\u003ca\nhref\u003d\"https://github.com/search?q\u003drepo%3Ajupyter-server%2Fjupyter_server+involves%3AYann-P+updated%3A2026-05-29..2026-06-17\u0026amp;type\u003dIssues\"\u003eactivity\u003c/a\u003e)\u003c/p\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003ch2\u003e2.19.0\u003c/h2\u003e\n\u003cp\u003e(\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/compare/v2.18.2...664e2255c71efe963f397b9f803dbcf503b5a920\"\u003eFull\nChangelog\u003c/a\u003e)\u003c/p\u003e\n\u003ch3\u003eEnhancements made\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eReturn \u003ccode\u003eunresolved\u003c/code\u003e stanza when kernel scope is\nunavailable for \u003ccode\u003eresolvePath\u003c/code\u003e (instead of failing with 404)\n\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1641\"\u003e#1641\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/MUFFANUJ\"\u003e\u003ccode\u003e@​MUFFANUJ\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e, \u003ca\nhref\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eBugs fixed\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003eRecreate notary store on failure to prevent save deadlock and data\nloss \u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/pull/1640\"\u003e#1640\u003c/a\u003e\n(\u003ca href\u003d\"https://github.com/krassowski\"\u003e\u003ccode\u003e@​krassowski\u003c/code\u003e\u003c/a\u003e,\n\u003ca href\u003d\"https://github.com/Carreau\"\u003e\u003ccode\u003e@​Carreau\u003c/code\u003e\u003c/a\u003e)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3\u003eMaintenance and upkeep improvements\u003c/h3\u003e\n\u003c!-- raw HTML omitted --\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e... (truncated)\u003c/p\u003e\n\u003c/details\u003e\n\u003cdetails\u003e\n\u003csummary\u003eCommits\u003c/summary\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/05a78ad879e69ef87e91b2714a8ebeb5ff9628a7\"\u003e\u003ccode\u003e05a78ad\u003c/code\u003e\u003c/a\u003e\nPublish 2.20.0\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/6cbee8d65e71abac851c4492fea987ad080580bd\"\u003e\u003ccode\u003e6cbee8d\u003c/code\u003e\u003c/a\u003e\nMerge commit from fork\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/333e700119ee0bcc0b5fcd4c158213d7c275c778\"\u003e\u003ccode\u003e333e700\u003c/code\u003e\u003c/a\u003e\nFix \u003ccode\u003etest_authorizer\u003c/code\u003e having a spurious comma in params (\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/issues/1664\"\u003e#1664\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/cccd543352d9be0365de56627b671cc8aa9cab0c\"\u003e\u003ccode\u003ecccd543\u003c/code\u003e\u003c/a\u003e\nFix CI: explicitly pass base-setup inputs to avoid strict validation\nfailures\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/cd16d715dfb1f84b2e5056317927fc930b811842\"\u003e\u003ccode\u003ecd16d71\u003c/code\u003e\u003c/a\u003e\nAlign docs for curve encryption with latest JEP version (\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/issues/1660\"\u003e#1660\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/e458061e6ee50368bbdb74153092fc8400704ee0\"\u003e\u003ccode\u003ee458061\u003c/code\u003e\u003c/a\u003e\nAdd a toggle to enable curve encryption for all kernels that support it\n(\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/issues/1638\"\u003e#1638\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/0ceeb4fb61be1deaaa7c1ff01325f7dd47db1c46\"\u003e\u003ccode\u003e0ceeb4f\u003c/code\u003e\u003c/a\u003e\nAdd note in RELEASE.md\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/b13f8a241b1111e402457e1d0b1cce252d8e1e5e\"\u003e\u003ccode\u003eb13f8a2\u003c/code\u003e\u003c/a\u003e\nMarkdown does not work.\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/e885b10a26c11caf109007a901153d1ac373c14d\"\u003e\u003ccode\u003ee885b10\u003c/code\u003e\u003c/a\u003e\nAdd GHSA reminder in prep-release\u003c/li\u003e\n\u003cli\u003e\u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/commit/0e28c901e8bc0953d61611fe8cb018460433288f\"\u003e\u003ccode\u003e0e28c90\u003c/code\u003e\u003c/a\u003e\nExclude problematic \u003ccode\u003epywinpty\u003c/code\u003e 3.0.4 version (\u003ca\nhref\u003d\"https://redirect.github.com/jupyter-server/jupyter_server/issues/1658\"\u003e#1658\u003c/a\u003e)\u003c/li\u003e\n\u003cli\u003eAdditional commits viewable in \u003ca\nhref\u003d\"https://github.com/jupyter-server/jupyter_server/compare/v2.18.0...v2.20.0\"\u003ecompare\nview\u003c/a\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/details\u003e\n\u003cbr /\u003e\n\n\n[![Dependabot compatibility\nscore](https://dependabot-badges.githubapp.com/badges/compatibility_score?dependency-name\u003djupyter-server\u0026package-manager\u003duv\u0026previous-version\u003d2.18.0\u0026new-version\u003d2.20.0)](https://docs.github.com/en/github/managing-security-vulnerabilities/about-dependabot-security-updates#about-compatibility-scores)\n\nDependabot will resolve any conflicts with this PR as long as you don\u0027t\nalter it yourself. You can also trigger a rebase manually by commenting\n`@dependabot rebase`.\n\n[//]: # (dependabot-automerge-start)\n[//]: # (dependabot-automerge-end)\n\n---\n\n\u003cdetails\u003e\n\u003csummary\u003eDependabot commands and options\u003c/summary\u003e\n\u003cbr /\u003e\n\nYou can trigger Dependabot actions by commenting on this PR:\n- `@dependabot rebase` will rebase this PR\n- `@dependabot recreate` will recreate this PR, overwriting any edits\nthat have been made to it\n- `@dependabot show \u003cdependency name\u003e ignore conditions` will show all\nof the ignore conditions of the specified dependency\n- `@dependabot ignore this major version` will close this PR and stop\nDependabot creating any more for this major version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this minor version` will close this PR and stop\nDependabot creating any more for this minor version (unless you reopen\nthe PR or upgrade to it yourself)\n- `@dependabot ignore this dependency` will close this PR and stop\nDependabot creating any more for this dependency (unless you reopen the\nPR or upgrade to it yourself)\nYou can disable automated security fix PRs for this repo from the\n[Security Alerts\npage](https://github.com/apache/iceberg-python/network/alerts).\n\n\u003c/details\u003e\n\nSigned-off-by: dependabot[bot] \u003csupport@github.com\u003e\nCo-authored-by: dependabot[bot] \u003c49699333+dependabot[bot]@users.noreply.github.com\u003e"
    },
    {
      "commit": "b9185ec1d031005c03f944c9bece6e3a5a725116",
      "tree": "7be2ca138eb28f4f347d48d80b8afe1acffdd453",
      "parents": [
        "fe7c749229be6a439a13371348ab741bba6fc940"
      ],
      "author": {
        "name": "Yuya Ebihara",
        "email": "ebyhry@gmail.com",
        "time": "Mon Jun 22 05:48:07 2026 +0900"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 13:48:07 2026 -0700"
      },
      "message": "Fix NotStartsWith residual evaluation to return correct result (#3503)\n\n# Rationale for this change\n\n- Fixes #3496\n\n## Are these changes tested?\n\nYes - the added test fails if we revert this PR\u0027s change.\n\n## Are there any user-facing changes?\n\nYes - this PR fixes a correctness issue of `NotStartsWith`.\n\n---------\n\nCo-authored-by: Kevin Liu \u003ckevinjqliu@users.noreply.github.com\u003e\nCo-authored-by: Kevin Liu \u003ckevin.jq.liu@gmail.com\u003e"
    },
    {
      "commit": "fe7c749229be6a439a13371348ab741bba6fc940",
      "tree": "11b6efad6322c62f7ebae111ae55cc28a40f16ad",
      "parents": [
        "a38bbe35ebb6105e4e353460fed57cb3d7fb8991"
      ],
      "author": {
        "name": "GayathriSrividya",
        "email": "gayathrirajavarapu7@gmail.com",
        "time": "Mon Jun 22 01:10:46 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sun Jun 21 12:40:46 2026 -0700"
      },
      "message": "fix: correct NOT STARTS WITH projection for truncated partitions (#3528)\n\ncloses #3493\n\n## Summary\n\nFixes incorrect projection of `NOT STARTS WITH` predicates for truncated\nstring/binary partition fields. The current implementation unsafely\ntruncates the filter literal without checking its length relative to the\ntruncate width.\n\n## Root Cause\n\nThe `TruncateTransform.project` method calls `_truncate_array` which\nblindly truncates the literal for both `STARTS WITH` and `NOT STARTS\nWITH` predicates:\n\n```python\nelif isinstance(pred, BoundNotStartsWith):\n    return NotStartsWith(Reference(name), _transform_literal(transform, boundary))\n```\n\nFor `NOT STARTS WITH \"hello\"` with `truncate[2]`, this produces:\n- Current (unsafe): `NOT STARTS WITH \"he\"` \n- Problem: The truncated partition contains all values starting with\n\"he\" (from \"hello\", \"heat\", \"hear\", etc.), so we cannot safely exclude\nall non-\"hello\" rows\n\n## Solution\n\nAdd special handling for `BoundNotStartsWith` in the `project` method\nfollowing the Java/Go reference behavior:\n\n- **prefix_length \u003c truncate_width**: Keep original `NOT STARTS WITH`\nliteral (safe)\n- **prefix_length \u003d\u003d truncate_width**: Project to `!\u003d` instead (safe\nequality check)\n- **prefix_length \u003e truncate_width**: Return `None` (no inclusive\nprojection possible)\n\n### pyiceberg/transforms.py\n- Add explicit `NOT STARTS WITH` handling before calling\n`_truncate_array`\n- Check literal length vs truncate width and apply correct projection\nrules\n\n### tests/test_transforms.py\n- Update `test_projection_truncate_string_not_starts_with` to expect\n`None` (prefix_length \u003e width is unsafe)\n- Add `test_projection_truncate_string_not_starts_with_shorter_literal`\n(prefix_length \u003d\u003d width → `!\u003d`)\n- Add `test_projection_truncate_string_not_starts_with_original_literal`\n(prefix_length \u003c width → original)\n\n## Validation\n- `make lint` ✓ (all pre-commit hooks pass)\n- `pytest tests/test_transforms.py` → 280 passed ✓\n- All 13 string truncate projection tests pass\n\n---------\n\nCo-authored-by: Gayathri Srividya Rajavarapu \u003cgayathrir@Gayathris-MacBook-Air.local\u003e\nCo-authored-by: Kevin Liu \u003ckevinjqliu@users.noreply.github.com\u003e"
    },
    {
      "commit": "a38bbe35ebb6105e4e353460fed57cb3d7fb8991",
      "tree": "9e3b0016cc5af023d5629049892dbcf5483f5241",
      "parents": [
        "3a3bc626657a4497d8d0011c564b0f902e3b9e84"
      ],
      "author": {
        "name": "Kevin Liu",
        "email": "kevinjqliu@users.noreply.github.com",
        "time": "Sat Jun 20 19:11:51 2026 -0400"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 16:11:51 2026 -0700"
      },
      "message": "feat: Add REST loadCredentials support (#3499)\n\n## Summary\n\n- add REST `loadCredentials` endpoint support\n- parse `LoadCredentialsResponse`\n- expose `RestCatalog.load_credentials(...)` with longest-prefix\nresolution for a target location\n\nContributes to #3495.\n\n## Notes\n\nThe pinned `apache/iceberg-rest-fixture:1.10.1` used by integration\ntests does not serve the `/credentials` route, so this is covered with\nREST catalog unit tests rather than fixture-backed integration tests.\n\n## Testing\n\n- `PYTHONPATH\u003d. pytest tests/catalog/test_rest.py -k \u0027load_credentials\nor storage_credentials\u0027`\n- `ruff check pyiceberg/catalog/rest/__init__.py\ntests/catalog/test_rest.py`\n- `ruff format --check pyiceberg/catalog/rest/__init__.py\ntests/catalog/test_rest.py`"
    },
    {
      "commit": "3a3bc626657a4497d8d0011c564b0f902e3b9e84",
      "tree": "1eea763867c11add18ed43c3176c9bc70c26fb76",
      "parents": [
        "aa39484a5f1614e2bf910d00234b2ad5aa1bb2b8"
      ],
      "author": {
        "name": "Yong Zheng",
        "email": "yongzheng0809@gmail.com",
        "time": "Sat Jun 20 16:21:35 2026 -0500"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 14:21:35 2026 -0700"
      },
      "message": "Add more examples for pyiceberg view (#3414)\n\n\u003c!--\nThanks for opening a pull request!\n--\u003e\n\n\u003c!-- In the case this PR will resolve an issue, please replace\n${GITHUB_ISSUE_ID} below with the actual Github issue id. --\u003e\nCloses #3413\n\n# Rationale for this change\n\nAdds more examples around view support.\n\n## Are these changes tested?\n\nYes. Those had been tested locally with local Polaris.\n\n## Are there any user-facing changes?\n\nNo.\n\n\u003c!-- In the case of user-facing changes, please add the changelog label.\n--\u003e\n\n---------\n\nCo-authored-by: Yuya Ebihara \u003cebyhry@gmail.com\u003e"
    },
    {
      "commit": "aa39484a5f1614e2bf910d00234b2ad5aa1bb2b8",
      "tree": "a19035e62553b8b6a7afadf7ed59d7cc66c4dbb8",
      "parents": [
        "6da06adfa82eda8d647060632115e75a35634b87"
      ],
      "author": {
        "name": "Sreesh Maheshwar",
        "email": "maheshwarsreesh@gmail.com",
        "time": "Sat Jun 20 19:34:39 2026 +0100"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Sat Jun 20 11:34:39 2026 -0700"
      },
      "message": "Refactor: extract `BaseScan` and `ManifestGroupPlanner` (#3511)\n\n# Rationale for this change\n\nSplit out of #3364 at the reviewers\u0027 request (to @rambleraptor\u0027s and\n@kevinjqliu\u0027s point that the architecture refactor and the new feature\nare easier to review separately).\n\nThis PR will be followed by\nhttps://github.com/apache/iceberg-python/pull/3512 that makes use of\nthis refactor to implement append scans more cleanly.\n\n**This PR is a pure refactor with no behavioural change.** The diff\nlooks large, but it is almost entirely code being moved, not changed.\n\n# Changes\n\n- Introduce `BaseScan(ABC)` as a superclass of `TableScan`, holding the\nsnapshot-independent surface: `table_metadata`, `io`, `row_filter`,\n`selected_fields`, `case_sensitive`, `options`, `limit`, the chaining\nhelpers (`select` / `filter` / `with_case_sensitive` / `update`), and\nthe format-converter sinks (`to_pandas` / `to_polars` / `to_duckdb` /\n`to_ray`) built on an abstract `to_arrow()`.\n- `TableScan` keeps everything snapshot-specific — `snapshot_id`,\n`catalog`, `table_identifier`, `snapshot()`, the snapshot-aware\n`projection()`, `use_ref()`, and abstract `count()` — so its existing\npublic surface is unchanged.\n- Extract `ManifestGroupPlanner` from `DataScan` (the `_build_*`\nevaluators, `_check_sequence_number`, and the manifest-entry /\nfile-scan-task planning) and route all of `DataScan`\u0027s local planning —\n`scan_plan_helper()` and `_plan_files_local()` — through it, so the\npartition / metrics / residual pipeline lives in exactly one place.\n\n# Back-compatibility\n\n- `to_arrow_batch_reader` stays concrete on `DataScan` and is **not**\nmade abstract on `BaseScan`, so external `TableScan` subclasses that\nwere valid before still instantiate.\n- `to_pandas` / `to_polars` become concrete defaults on `BaseScan`, and\n`to_duckdb` / `to_ray` move up to `BaseScan` too. This **loosens**\n`TableScan`\u0027s abstract contract (they were abstract on `TableScan`\nbefore) without breaking existing subclasses.\n- All docstrings and explanatory comments are preserved.\n\n# Are these changes tested?\n\nThe existing `DataScan` unit and integration tests exercise the\nrefactored planning path unchanged. A regression test is added for the\nno-current-snapshot planning path, which now flows through\n`ManifestGroupPlanner`.\n\n# Are there any user-facing changes?\n\nNo. Some previously-`DataScan`-only converters (`to_duckdb` / `to_ray`)\nare now inherited by `TableScan` as well, which is purely additive.\n\n---------\n\nCo-authored-by: Claude Opus 4.8 (1M context) \u003cnoreply@anthropic.com\u003e\nCo-authored-by: Kevin Liu \u003ckevinjqliu@users.noreply.github.com\u003e"
    },
    {
      "commit": "6da06adfa82eda8d647060632115e75a35634b87",
      "tree": "a5cf047ec7ac795d6e8288152ffc584bdb71a061",
      "parents": [
        "a1e12ad7d9ac253e9c134fc53feb2c7cd1031079"
      ],
      "author": {
        "name": "GayathriSrividya",
        "email": "gayathrirajavarapu7@gmail.com",
        "time": "Thu Jun 18 12:24:10 2026 +0530"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Thu Jun 18 08:54:10 2026 +0200"
      },
      "message": "feat: add `dictionary_columns` to Arrow scans (#3461)\n\nCloses #3170\n\n## Rationale\n\nColumns that contain large or frequently repeated string values (e.g.\nJSON blobs, low-cardinality categoricals) can exhaust memory when\nPyArrow loads them as plain string arrays. PyArrow\u0027s Parquet reader\nnatively supports dictionary-encoded reads via its `dictionary_columns`\nkwarg, which deduplicates values and can dramatically reduce peak memory\nusage.\n\nThis was previously discussed in #3168 and a prior implementation\n(#3234) was closed as stale.\n\n## Changes\n\n- Added `dictionary_columns: tuple[str, ...] \u003d ()` to `Table.scan()`,\n`TableScan.__init__`, and `StagedTable.scan()`.\n- Forwarded through `DataScan.to_arrow()` and `to_arrow_batch_reader()`\n→ `ArrowScan.__init__` → `_task_to_record_batches` →\n`_get_file_format()`.\n- Only applied when `task.file.file_format \u003d\u003d FileFormat.PARQUET`;\nsilently ignored for ORC (which does not support this kwarg).\n\n## Usage\n\n```python\n# Read the \"payload\" column as dictionary-encoded to save memory\ndf \u003d table.scan(dictionary_columns\u003d(\"payload\",)).to_arrow()\n```\n\n## Verification\n\n- Added `test_dictionary_columns_produces_dict_encoded_output` —\nconfirms the requested column is dict-encoded, non-requested columns are\nplain, and values are identical.\n- `make lint` ✓\n- `pytest tests/table/ tests/io/test_pyarrow.py` ✓\n\n---------\n\nCo-authored-by: Gayathri Srividya Rajavarapu \u003cgayathrir@Gayathris-MacBook-Air.local\u003e\nCo-authored-by: Claude Sonnet 4.6 \u003cnoreply@anthropic.com\u003e"
    },
    {
      "commit": "a1e12ad7d9ac253e9c134fc53feb2c7cd1031079",
      "tree": "7bdc13e3fce3fd5bb397090d31a9f146c4ce81cd",
      "parents": [
        "9d2a5e77e6d06622d59b0570425e55aab98e5fc7"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Tue Jun 16 19:05:13 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 19:05:13 2026 +0200"
      },
      "message": "Build: Bump aiohttp from 3.14.0 to 3.14.1 (#3516)"
    },
    {
      "commit": "9d2a5e77e6d06622d59b0570425e55aab98e5fc7",
      "tree": "e77d7c9f0a1b6d38732107cda0ea623c682f1c48",
      "parents": [
        "cf78ac7bd8cb7fd984b46f2ca2b9116364646756"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Tue Jun 16 19:05:04 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 19:05:04 2026 +0200"
      },
      "message": "Build: Bump cryptography from 46.0.7 to 48.0.1 (#3515)"
    },
    {
      "commit": "cf78ac7bd8cb7fd984b46f2ca2b9116364646756",
      "tree": "cab99ffabf3fe05f787ee6a31ccaed03ba78dc2c",
      "parents": [
        "ef96d3a31ccd62c1615eb7929b11d8c40ac5bd07"
      ],
      "author": {
        "name": "dependabot[bot]",
        "email": "49699333+dependabot[bot]@users.noreply.github.com",
        "time": "Tue Jun 16 19:04:54 2026 +0200"
      },
      "committer": {
        "name": "GitHub",
        "email": "noreply@github.com",
        "time": "Tue Jun 16 19:04:54 2026 +0200"
      },
      "message": "Build: Bump tornado from 6.5.6 to 6.5.7 (#3514)"
    }
  ],
  "next": "ef96d3a31ccd62c1615eb7929b11d8c40ac5bd07"
}
