Compiled metadata system
========================

.. py:currentmodule:: objc


Starting with version 2.4 PyObjC provides a more efficient, lazy loading
metadata system. This can greatly reduce the memory use and startup time
for PyObjC based applications while still providing full access to
Cocoa APIs.

Creating a framework wrapper
----------------------------

A framework wrapper with the new metadata system is always a
python package. The package contains an "__init__.py" file
that creates the lazy loader, a "_metadata.py" file with the
compiled metadata and optionally other modules and extensions.

The general structure of the "__init__.py" file is:

.. sourcecode:: python

   """
   Python mapping for the AVFoundation framework.

   This module does not contain docstrings for the wrapped code, check Apple's
   documentation for details on how to use these functions and classes.
   """

   def _setup():
       import sys

       import CoreAudio
       import CoreMedia
       import Foundation
       import objc
       from AVFoundation import _metadata
       import AVFoundation._AVFoundation
       from AVFoundation._inlines import _inline_list_

       dir_func, getattr_func = objc.createFrameworkDirAndGetattr(
           name="AVFoundation",
           frameworkIdentifier="com.apple.avfoundation",
           frameworkPath=objc.pathForFramework("/System/Library/Frameworks/AVFoundation.framework"),
           globals_dict=globals(),
           inline_list = _inline_list_,
           parents = (AVFoundation._AVFoundation, CoreAudio, CoreMedia, Foundation),
           initialdict={},
           metadict=_metadata.__dict__)

       globals()['__dir__'] = dir_func
       globals()['__getattr__'] = getattr_func

       del sys.modules["AVFoundation._metadata"]

   globals().pop("_setup")()


The framework name, identifier and path should be replaced by
the correct values for the wrapped framework. The import of "Foundation"
can be replaced by imports of other framework this framework relies on
(also add those to the last argument of :func:`objc.createFrameworkDirAndGetattr`).

Contents of the "_metadata" module
----------------------------------

The exact contents of the "_metadata" module will be described later.

Generating the "_metadata" module
---------------------------------

The "objective-metadata" project contains a tool for collecting information
about frameworks and compiling that information and manual additions into
a "_metadata" module.

That project currently is not a stable as I'd like, this documentation will
be updated with more information when that changes.

.. todo:: include reference to that project and its documentation

API description
---------------

.. class:: ObjCLazyModule(name, frameworkIdentifier, frameworkPath, metadict, [inline_list[, initialdict[, parents]]])

   A subclass of the built-in :class:`module` type that adds lazy-loading of values defined
   in PyObjC metadata.

   :param frameworkIdentifier: the *bundle_identifier* argument for a call to :func:`loadBundle`
   :param frameworkPath:       the *bundle_path* argument for a call to :func:`loadBundle`
   :param metadict:            the dictionary with metadata, usually the \__dict__ of a module generated by
                               the metadata compiler.
   :param inline_list:         a capsule object with function definitions, see :func:`loadFunctionList` for more information.
   :param initial_dict:        additional values to add to the module dictionary
   :param parents:             a list of parent modules, the module behaves as if those modules were imported using
                               ``from parent parent import *``, but lazily fetches definitions on first access.

   .. note::

      This is the primary entry point for the framework wrappers shipped with PyObjC.

   .. versionchanged:: 10.0

      This class is now deprecated, use :func:`objc.createFrameworkDirAndGetattr` instead


.. function:: createFrameworkDirAndGetattr(name, frameworkIdentifier, frameworkPath, globals_dict, metadict, inline_list, parents)

   All arguments are required keyword arguments.

   Loads a framework bundle and returns the module level ``__dir__`` and ``__getattr__`` functions for
   use in a framework binding. The example at the top of this page shows how this API should be
   used.

   ;param name:                name of the framework
   :param frameworkIdentifier: the *bundle_identifier* argument for a call to :func:`loadBundle`
   :param frameworkPath:       the *bundle_path* argument for a call to :func:`loadBundle`
   :param globals_dict:        the *__dict__* of a framework bindings module
   :param metadict:            the dictionary with metadata, usually the \__dict__ of a module generated by
                               the metadata compiler.
   :param inline_list:         a capsule object with function definitions, see :func:`loadFunctionList` for more information. Use ``None`` if no inline list is used.
   :param parents:             a list of parent modules, the module behaves as if those modules were imported using
                               ``from parent parent import *``, but lazily fetches definitions on first access.
