<commit_before><commit_msg>Start documenting the object model<commit_after>pikepdf Object Model
********************

This section covers the object model pikepdf uses in more detail.

A ``pikepdf.Object`` is a Python wrapper around a C++ ``QPDFObjectHandle`` which,
as the name suggests, is a handle (or pointer) to a data structure in memory,
or possibly a reference to data that exists in a file. Importantly, an object
can be a scalar quantity (like an integer) or a compound quatity (like a list
or dict, that contains other objects). The fact that the C++ class involved here
is an object handle is an implementation detail; it shouldn't matter for a 
pikepdf user.

There is something of an impedance mismatch between Python's strict dynamic
typing and a C++ library that effectively has a dynamic variant type. Currently
this is managed by **not** subclassing ``pikepdf.Object``. Instead pikepdf
``pikepdf.Object`` implements all of the methods it could ever use.

For convenience, the ``repr()`` of a ``pikepdf.Object`` will display a
Python expression that replicates the existing object (when possible), so it
will say:

.. code-block:: python

    >>> three = pikepdf.Integer(3)
    pikepdf.Integer(3)

But in reality it's just a PDF object, with no subclassing:

.. code-block:: python

    >>> three.__class__.__name__
    pikepdf.Object

Making PDF objects
==================

You may construct a new object with one of the factory functions:

*   ``pikepdf.Integer``
*   ``pikepdf.Boolean``
*   ``pikepdf.Array``
*   ``pikepdf.Dictionary``
*   ``pikepdf.Real`` - decimal numbers, similar to ``decimal.Decimal``
*   ``pikepdf.Name`` - the type used for keys in PDF Dictionary objects
*   ``pikepdf.String`` - a text string 
    (treated as ``bytes`` and ``str`` depending on context)
*   ``pikepdf.Null`` - equivalent to ``None``

For example, a PDF ``Boolean`` may be constructed as 

.. code-block:: python

    >>> pikepdf.Boolean(True)
    pikepdf.Boolean(True)

There are a few other factory functions for special PDF objects that don't
map to Python as neatly. We'll look at these later.

*   ``pikepdf.Operator`` - a special object involved in processing content streams
*   ``pikepdf.Stream`` - a special object similar to a ``Dictionary`` with compressed binary data attached
*   ``pikepdf.Inlineimage`` - an image that is embedded in content streams

The great news is that it's often unnecessary to construct ``pikepdf.Object`` objects
when working with pikepdf. Python types are transparently *converted* to the appropriate
pikepdf object when passed to pikepdf APIs – when possible. However, pikepdf sends 
``pikepdf.Object`` types back to Python on return calls, in most cases, because
pikepdf needs to keep track of objects that came from PDFs originally.

Because Python types are converted to pikepdf types, references will be lost.

{'fraction_non_alphanumeric': 0.09842931937172775, 'fraction_numerical': 0.0006980802792321117, 'mean_word_length': 4.367041198501872, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 12, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '3899282', 'n_tokens_mistral': 791, 'n_tokens_neox': 741, 'n_words': 379}