pyobjc / Doc / structure.txt

===============================
Structure of the PyObjC package
===============================

Introduction
------------

This document gives an overview of the PyObjC for developers (of the package).

One of the sections describes how all of it works, and some of the limitations.

This document is a incomplete, it should be updated.


Methods
-------

Classes are scanned for methods when the Python wrapper for a class is created.
We then create Python wrappers for those methods.  This way users can use the
normal Python introspection methods to check which methods are available.

There are several occasions when these method tables are rescanned, because
classes can grow new methods when categories are loaded into the runtime.
Additionally, it is known that some Cocoa frameworks in Mac OS X change
their method tables when the first instance is created.

Subclassing
-----------

It is possible to subclass Objective-C classes from Python.  These classes
end up in a structure containing both a Python type object and an Objective-C
class.  Instances of these classes also contain both a Python instance and
an Objective-C object.

The first Python subclass of an Objective-C class introduces a new instance
variable in the Objective-C object to store the pointer to the Python half of
the cluster.  This variable is always referenced by name.  The Python half is 
a subclass of ``objc_object`` that already contains a pointer to an Objective-C 
object.  This first subclass also introduces a number of class and instance
methods that the PyObjC bridge uses to maintain the illusion of a single
object on both sides.  Check class-builder.m for details.


Directory structure
-------------------

Doc/
  Documentation

Examples/
  Example scripts and applets.

Lib/
  The pure Python parts of the packages that comprise PyObjC.  Currently
  contains the packages 'objc', 'PyObjCScripts', 'PyObjCTools' and the
  semi-automatically generated wrappers for the 'AddressBook',
  'AppKit', 'ExceptionHandling', 'Foundation', 'InterfaceBuilder', 'Message',
  'PreferencePanes', 'ScreenSaver', 'SecurityInterface' and 'WebKit'
  frameworks.

Modules/
  Extension modules related to the packages in 'Lib'.

Scripts/
  Scripts used during building and/or development of PyObjC.

Installer Package/
  Resources used for building the Apple Installer packages.

Xcode/
  Xcode templates for PyObjC development.

libffi-src/
  A local copy of libffi, the Foreign Function Interface library used by
  PyObjC.

setup-lib/
  Modules used by setup.py for building and distributing PyObjC.

source-deps/
  Local copies of Python packages and modules used by PyObjC that are not
  expected to be found in the minimum supported version of Python.  These
  are not automatically installed by setup.py, but some may be included in
  a bdist_mpkg installer (currently, just py2app).

Reference counts
----------------

The Objective-C rules for reference counts are pretty easy: A small number
of class methods (``alloc``, ``allocWithZone:``, ``copy``, ...) transfer
object ownership to the caller.  For all other objects you have to call
``retain`` if you want to keep a reference.  This includes all factory
methods, such as ``[NSString stringWithCString:"bla"]``!

When programming Cocoa in Python, you rarely need to worry about
reference counts: the ``objc`` module makes this completely transparent to
user.  This is mostly implemented in ``[de]pythonify_c_value``.  Additonal
code is needed when calling methods that transfer ownership of their return
value (as described above) and when updating a instance variable in an
Objective-C object (retain new and release old, in that order).  Both are
implemented.

Strings
-------

Python ``unicode`` instances are proxied by the ``OC_PythonUnicode`` subclass
of ``NSString``.  This is a proxy, and will maintain the identity of the
original ``unicode`` instance.

``NSString`` instances are represented in Python as a subtype of ``unicode``:
``objc.pyobjc_unicode``.  This performs a conversion, because Python's
``unicode`` type is immutable, but it also maintains a *reference* to the
original ``NSString``.  ``NSString`` and ``NSMutableString`` methods are
available from the ``objc.pyobjc_unicode`` object, though they do not show up
via Python's introspection mechanisms.  In order to get the latest Python
representation of a ``NSMutableString``, use the return value of its ``self()``
method.

Python ``str`` instances are proxied by the ``OC_PythonString`` subclass of
``NSString``.  This is a proxy, and will maintain the identity of the
original ``str`` instance.  ``OC_PythonString`` will use the default encoding
of ``NSString``, so its results might be surprising if you are using non-ASCII
text.  It is recommended that you use ``unicode`` whenever possible.  In order
to help you determine where you are not using ``unicode``, it is possible
to trigger an ``objc.PyObjCStrBridgeWarning`` warning whenever a ``str``
instance crosses the bridge::

      import objc
      objc.setStrBridgeEnabled(False)

To promote these to an exception, do the following::

      import objc
      import warnings
      warnings.filterwarnings('error', objc.PyObjCStrBridgeWarning)
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.