# v3

## v3.2.0

- Fixed support for outline items that have PDF 1.1-style named destinations. #258, #261

- We now issue a warning if an unnecessary password was provided when opening an unencrypted PDF.

## v3.1.1

- Fixed errors that occurred on `import pikepdf` for an extension module built with pybind11 2.8.0.

## v3.1.0

- Extraction of common inline image file formats is now supported.

- Some refactoring and documentation improvements.

## v3.0.0

### Breaking changes

- libqpdf 10.3.1 is now required and other requirements were adjusted.

- pybind11 2.7.1 is now required.

- Improved page API. `Pdf.pages` now returns `Page` instead of page object dictionaries, so it is no longer necessary to wrap page objects as in the previous idiom `page = Page(pdf.pages[0])`. In most cases, if you use the Dictionary object API on a page, it will automatically do the right thing to the underlying dictionary.

- Improved content stream API. `parse_content_stream` now returns a list of `pikepdf.ContentStreamInstruction` or `pikepdf.ContentStreamInlineImage`. These are “duck type”-compatible with the previous data structure but may affect code that strongly depended on the return types. `unparse_content_stream` still accepts the same inputs.

- `TokenType.name` and `ObjectType.name` were renamed to `TokenType.name_` and `ObjectType.name_`, respectively. Unfortunately, Python’s `Enum` class (of which these are both a subclass) uses the `.name` attribute in a special way that interfered.

- Deprecated or private functions were removed: - `Object.page_contents_*` (use `Page.contents_*`) - `Object.images` (use `Page.images`) - `Page._attach` (use the new attachment API) - `Stream(obj=)` (deprecated `obj` parameter removed) - `Pdf.root` (use `Pdf.Root`) - `Pdf._process` (use `Pdf.open(BytesIO(...))` instead)

- `pikepdf.Page.calc_form_xobject_placement()` previously returned `str` when it should have returned `bytes`. It now returns the correct type.

- `pikepdf.open()` and `pikepdf.save()`, and their counterparts in `pikepdf.Pdf`, now expect keyword arguments for all except the first parameter.

- Some other functions have stricter typing, required keyword arguments, etc., for clarity.

- If a calculating the `repr()` of a page, we now describe a reference to that page rather than printing the page’s representation. This makes the output of `repr(obj)` more useful when examining data structures that reference many pages, such as `/Outlines`.

- Build scripts and wheel building updated.

- We now internally use a different API call to close a PDF in libqpdf. This may change the behavior of attempts to manipulate a PDF after it has been closed. In any case, accessing a closed file was never supported.

### New functionality

- Added `pikepdf.NameTree`. We now bind to QPDF’s Name Tree API, for manipulating these complex and important data structures.

- We now support adding and removing PDF attachments. #209

- Improved support for PDF images that use special printer colorspaces such as DeviceN and Separation, and support extracting more types of images. #237

- Improved error message when `Pdf.save()` is called on PDFs without a known source file.

- Many documentation fixes to StreamParser, return types, PdfImage.

- `x in pikepdf.Array()` is now supported; previously this construct raised a TypeError. #232

- It is now possible to test our cibuildwheel configuration on a local machine.

### Fixes

- `repr(pikepdf.Stream(...))` now returns syntax matching what the constructor expects.

- Fixed certain wrong exception types that occurred when attempting to extract special printer colorspace images.

- Lots of typing fixes.