# v3

## v3.2.0

- Fixed support for outline items that have PDF 1.1-style named destinations.
  {issue}`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
  {class}`pikepdf.ContentStreamInstruction` or {class}`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)
- {meth}`pikepdf.Page.calc_form_xobject_placement` previously returned `str` when
  it should have returned `bytes`. It now returns the correct type.
- {func}`pikepdf.open` and {func}`pikepdf.save`, and their counterparts in
  {class}`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 {class}`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. {issue}`209`
- Improved support for PDF images that use special printer colorspaces such as
  DeviceN and Separation, and support extracting more types of images. {issue}`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. {issue}`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.
