# v10

## Breaking changes for v10.x
- Dropped Python 3.9 compatibility, since it is end of life. Python 3.10 through
  3.14 are supported.
- Dropped macOS 13 support, since it is end of life.
- Dropped macOS 14 Intel wheels, because GitHub doesn't provide a way to build
  them - macOS 15 Intel works fine.
- Dropped deprecated method `Pdf.check()` (use `.check_pdf_syntax()`).

pikepdf now declares unstable "support" for freethreading, and does not publish
freethreading wheels. All tests seem to pass, but that's because the existing
tests don't try to create race conditions. Must be compiled manually.

## v10.7.1

- Fixed build to continue generating Python version specific wheels for
  3.12 and 3.13 due to open issue in nanobind. Fixes :issue:`723`. Thanks
  @mgorny for reporting.
- Improved CI build to perform more detailed tests using python3-dbg (debug
  build) which has more assertions and would have uncovered this issue.

## v10.7.0

- Yanked release from PyPI due to segfaults on Python 3.12 and 3.13; fixed in
  10.7.1.
- Python 3.12+ are now built with abi3 (the Stable ABI). Earlier versions and
  freethreading builds continue to be built against the specific Python versions.
- Remove manual hack to generate docs/requirements.txt for the readthedocs.org.

## v10.6.0

- Released v10.6.0 with version bump only.

## v10.6.0rc2

- Fixed a regression during nanobind migration (exception hierarchy
  unintentionally changed).

## v10.6.0rc1

- Replaced pybind11 with nanobind and added full freethreading support. pikepdf
  binary size is now both ~20% smaller and about 10% faster thanks to nanobind.

## v10.5.1

- Updated lockfile to avoid a PyJWT CVE. We only depend use PyJWT via pygithub
  for developer release tooling not in pikepdf itself, so this is
  inconsequential for pikepdf users but does silence automated security
  advisories.
- Suppressed GCC ``-Wpsabi`` note about C++17 ABI change for ``std::pair`` in
  pybind11 headers.

## v10.5.0

- Fixed logger in ``ctm`` module using ``__file__`` instead of ``__name__``,
  which produced unhelpful log names. :issue:`712`
- Modernized README.
- Test all README code blocks instead of just one.

## v10.4.0

- Enums are now proper Python ``enum.Enum``/``enum.IntFlag`` types (PEP 435
  compliant), migrated from pybind11's deprecated ``py::enum_`` to
  ``py::native_enum``.
- Reimplemented the PDFDocEncoding codec in pure Python using the standard
  library charmap pattern, removing the C++ dependency on qpdf for encoding.
- Upgraded to qpdf 12.3.2.
- Fixed incorrect docstrings for ``StreamDecodeLevel``. :issue:`708`
- Fixed type stubs: added PEP 570 positional-only markers, and corrected
  ``index()`` signature.

## v10.3.0

- Fixed UnicodeDecodeError when listing keys of a dictionary containing invalid
  UTF-8. Thanks @qooxzuub. :issue:`696`
- Fixed an issue where opening a PDF with duplicate form field names would cause a
  crash. Accessing a duplicate field by name now returns a proxy list of all matching
  fields. Thanks @qooxzuub. :issue:`697`
- Added `.values()` accessor to `Object` for iterating over dictionary values. Thanks @qooxzuub.:issue:`699,697`
- Added `.copy()` and `.update()` methods to `Dictionary`. Thanks @qooxzuub.:issue:`700`
- Improved `Object.copy` implementation and added type stubs. Thanks @qooxzuub.:issue:`702`
- Fixed missing return in `SimpleFont._encode_diffmap()`. Thanks @lachlan.charlick :issue:`706`
- Improved error messages for invalid dictionary access. Thanks @qooxzuub.:issue:`701`
- Lazy load lxml and Pillow to improve import time. Thanks @qooxzuub. :issue:`704`
- Improved `atomic_overwrite` robustness for restricted directories and special files. :issue:`695`

## v10.2.0

- Fixed `unparse_content_stream()` not preserving literal strings when given raw
  Python tuples. :issue:`689`
- The {func}`pikepdf.explicit_conversion` context manager is now thread-local and
  takes precedence over the global setting from {func}`pikepdf.set_object_conversion_mode`.
  Nested context managers are supported via a depth counter.
- Moved explicit conversion functions to their own module for better code organization.
- Improved C++ test coverage to 97.5% (from 96.4% line coverage, 94.9% to 95.1% function coverage).

## v10.1.0

- Added {class}`pikepdf.NamePath` for ergonomic access to deeply nested PDF
  structures. NamePath provides a single-operation traversal with helpful error
  messages showing exactly where traversal failed.
  See {ref}`Accessing nested objects with NamePath <namepath>` for details.
- Added explicit scalar types: {class}`pikepdf.Integer`, {class}`pikepdf.Boolean`,
  and {class}`pikepdf.Real`. When explicit conversion mode is enabled, these types
  are returned instead of Python native types (`int`, `bool`, `Decimal`), enabling
  better type safety and static type checking.
- Added {func}`pikepdf.set_object_conversion_mode` and
  {func}`pikepdf.get_object_conversion_mode` to control conversion behavior globally.
- Added {func}`pikepdf.explicit_conversion` context manager for temporarily enabling
  explicit conversion mode.
- Added safe accessor methods to {class}`pikepdf.Object`: {meth}`~pikepdf.Object.as_int`,
  {meth}`~pikepdf.Object.as_bool`, {meth}`~pikepdf.Object.as_float`, and
  {meth}`~pikepdf.Object.as_decimal` with optional default parameters for type-safe
  access to scalar values.
- `pikepdf.Integer` and `pikepdf.Real` now support full arithmetic operations with
  both `int` and `float` operands, including true division (`/`).

## v10.0.3

- Fixed an issue where `PdfImage.as_pil_image()` would create additional unused objects in the PDF that called it.
- Fixed a shutdown segfault in the alpha release of Python 3.15.
- Fixed `Pdf.show_xref_table()` not actually showing its output.
- Pin test dependencies python-xmp-toolkit to < 2.1.0. python-xmp-toolkit 2.1.0 is effectively a breaking change, requiring a new version of libexempi to be installed that is not available on some cibuildwheel builders. As a workaround, we have pinned the older version. We only use python-xmp-toolkit for testing to confirm correctness--pikepdf has its own XML-based implementation of XMP.

## v10.0.2

- Fixed presentation of strings using `unparse_content_stream` - if the stream can be represented using PdfDocEncoding, it is rendered in that way for ease of reading. :issue:`682`
- Reformatted C++ source.

## v10.0.1

- Fixed issue with performing equality test on dictionaries with cyclic subgraphs.
  :issue:`677`

## v10.0.0

See breaking changes for v10.0.0 above.

