Removing the obvious OS9-only documents§

This commit is contained in:
Jack Jansen 2003-11-19 14:54:25 +00:00
parent 28ecf70db5
commit d338b6e317
16 changed files with 0 additions and 2513 deletions

View File

@ -1,424 +0,0 @@
<HTML>
<HEAD>
<TITLE>Building MacPython-OS9 from source</TITLE>
</HEAD>
<BODY>
<H1>Building MacPython-OS9 from source</H1>
<HR>
This document explains how to build MacPython-OS9 from source. This is
necessary if you want to make modifications to the Python core. Building
Python is not something to be undertaken lightly, you need a reasonable
working knowledge of the CodeWarrior development environment, a good net
connection and probably quite some time too. <p>
Note that if you only want to build new extension modules you don't need to
build Python from source, see the <a href="#extending">note on extending Python</a>.<p>
The information density in this file is high, so you should probably
print it and read it at your leasure. Most things are explained only
once (and probably in the wrong place:-). <p>
<blockquote>
First a warning: this information may become outdated if a new CodeWarrior is
released after MacPython. The
<a href="http://www.cwi.nl/~jack/macpython.html">MacPython homepage</a> will
hopefully have updated instructions in that case. These instructions are for CW7,
it is rumoured you may encounter some problems with newer versions of CodeWarrior.
</blockquote>
I am interested in feedback on this document, send your
comments to the <A
HREF="http://www.python.org/sigs/pythonmac-sig/">Mac Python Special
Interest Group</A>.
<H2>What you need.</H2>
The following things you definitely need:
<UL>
<LI> You need a MacPython source distribution, of course. You can
obtain one via <A HREF="http://www.cwi.nl/~jack/macpython.html">
http://www.cwi.nl/~jack/macpython.html</A> (which has up-to-date links
to the other packages needed too) and possibly also from the standard
<A HREF="ftp://ftp.python.org/pub/python/mac">python.org ftp
site</A>. <BR>
A better alternative is to check the sources straight out of the CVS
repository, see below. Most of the packages mentioned here are also
available through CVS. Check the section on <a href="#cvs">CVS
repository use</a> below.
<LI> You need MetroWerks CodeWarrior. The current distribution has
been built with CodeWarrior Pro 7.1. Ordering information is
available on the <A HREF="http://www.metrowerks.com/">MetroWerks
homepage</A>. Building Python with MPW, Think/Symantec C or the OSX
developer tools is impossible without major surgery.
<LI> You need GUSI version 2, the Grand Unified Socket Interface, by
Matthias Neeracher. The original GUSI is obtainable from <A
HREF="ftp://gusi.sourceforge.net/pub/gusi/">
ftp://gusi.sourceforge.net/pub/gusi/</A>. At
the moment Python is built with a modified version of GUSI
with Carbon adaptations, so it may be better to check the <A
HREF="http://www.cwi.nl/~jack/macpython.html">MacPython homepage</A>
for a GUSI that is most easily used for building Python.
</UL>
<A NAME="optional">The MacPython project files are configured to
include a plethora of optional modules</A>, and these modules need a
number of extra packages. To use the project files as-is you have to
download these packages too. Python has all such modules as
dynamically loaded modules, so if you don't need a certain package it
suffices to just refrain from builing the extension module.
Here are the locations for the various things
you need:
<UL>
<LI> Waste, a TextEdit replacement written by Marco Piovanelli, <A
HREF="mailto:piovanel@kagi.com">&lt;piovanel@kagi.com&gt;</A>. Python
was built using version 2.0, which is included in the CodeWarrior
package. You can also obtain it from <A
HREF="http://www.merzwaren.com/waste">&lt;http://www.merzwaren.com/waste&gt;</A>
and various other places.
<LI> Gdbm library for the Mac. Available from Jack's Mac software page at
<A HREF="http://www.cwi.nl/~jack/macsoftware.html">
http://www.cwi.nl/~jack/macsoftware.html</A> and <A HREF="ftp://ftp.cwi.nl/pub/jack/mac">
ftp://ftp.cwi.nl/pub/jack/mac</A>.
<LI> JPEG library by the Independent JPEG Group. A version including
Mac projects can be found at Jack's page mentioned above.
The most recent JPEG library can always be obtained from <A
HREF="ftp://ftp.uu.net/graphics/jpeg/">ftp://ftp.uu.net/graphics/jpeg/</A>.
<LI> The netpbm/pbmplus, libtiff, zlib and png libraries. The netpbm distribution
(which includes libtiff) is generally available on Internet ftp
servers. For Python pbmplus, an older incarnation of netpbm, is
functionally identical to netpbm, since Python only uses the library
and not the complete applications. A distribution with correct
projects and library source only is available from, you guessed it, Jack's Mac software
page mentioned above.
</UL>
<H2>Setting Up</H2>
Now that you have collected everything you should start with building
the various parts. If you don't want to fix
access paths try to set things up as follows:
<PRE>
Top-level-folder:
GUSI2
imglibs
jpeg
netpbm
libtiff
zlib
png
gdbm
Python
Modules
...
Mac
Modules
Build
...
</PRE>
If your setup of the libraries is exactly the same as mine (which is
not very likely, unless you happen to work from the same CVS
repository) you can use the project <code>buildlibs.prj</code> in the
<code>:Mac:Build</code> folder to build all needed libraries in one
fell swoop, otherwise you will have to build the libraries one by
one. <p>
First build GUSI, the Carbon variant.
<p>
Next, in
<code>libjpeg</code>, <code>pbmplus</code>,
<code>zlib</code>, <code>libpng</code>, <code>gdbm</code>,
and<code>libtiff</code> you build all projects. Usually the projects are in "mac"
subfolders, sometimes they are in the main folder. Tcl/tk is a special
case, see below.
<H2>The organization of the Python source tree</H2>
Time for a short break, while we have a look at the organization of
the Python source tree. At the top level, we find the following
folders:
<DL>
<DT> Demo
<DD> Demo programs that are not Mac-specific. Some of these may not
work.
<DT> Extensions
<DD> Extensions to the interpreter that are not Mac-specific. Contains
the <code>img</code>, <code>Imaging</code> and <code>Numerical</code> extensions
in this distribution.
<DT> Grammar
<DD> The Python grammar. Included for reference only, you cannot build
the parser on a Mac.
<DT> Include
<DD> Machine-independent header files.
<DT> Modules
<DD> Machine-independent optional modules. Not all of these will work
on the Mac.
<DT> Lib
<DD> Machine-independent modules in Python.
<DT> Lib:lib-dynload
<DD> This is where the dynamically-loaded plugin modules live.
<DT> Lib:plat-mac
<DD> This is where most of the Mac-specific modules live. The modules here
are available both in MacPython-OS9 and MacPython-OSX.
<DT> Objects
<DD> Machine-independent code for various object types. Most of these are
not really optional: the interpreter will not function without them.
<DT> Parser
<DD> The Python parser (machine-independent).
<DT> Python
<DD> The core interpreter. Most files are machine-independent, some
are unix-specific and not used on the Mac.
<DT> Tools
<DD> Tools for python developers. Contains <code>modulator</code> which
builds skeleton C extension modules, <code>bgen</code> which generates
complete interface modules from information in C header files and
<code>freeze</code> which is used to turn Python scripts into real
applications (used by MacFreeze and BuildApplication) There are some
readme files, but more documentation is sorely needed.
</DL>
The mac-specific stuff lives in the <code>Mac</code> folder:
<DL>
<DT> Build
<DD> This is where the project files live and where you build the
libraries, shared libraries, executables and plugin modules. All the
resulting binaries, except for intermedeate results, are deposited in
the toplevel folder or the :Lib:lib-dynload folder (for plugin modules).
<DT> Compat
<DD> Unix-compatability routines. Most of these are not used anymore,
since GUSI provides a rather complete emulation, but you may need
these if you are trying to build a non-GUSI python.
<DT> Demo
<DD> Mac-specific demo programs, some of them annotated.
<DT> Include
<DD> Mac-specific but compiler-independent include files.
<DT> Lib
<DD> MacPython-OS9 specific standard modules which are not shared with
MacPython-OSX.
<DT> Modules
<DD> Mac-specific builtin modules. Theoretically these are all
optional, but some are rather essential (like
<code>macosmodule</code>). A lot of these modules are generated with
<code>bgen</code>, in which case the bgen input files are included so
you can attempt to regenerate them or extend them.
<DT> MPW
<DD> MPW-specific files. These have not been used or kept up-to-date
for a long time, so use at your own risk.
<DT> mwerks
<DD> Mwerks-specific sources and headers. Contains glue code for
Pythons shared-library architecture, a replacement for
<code>malloc</code> and a directory with various projects for building
variations on the Python interpreter. The <code>mwerks_*.h</code>
files here are the option-setting files for the various interpreters
and such, comparable to the unix command-line <code>-D</code> options
to the compiler. Each project uses the correct option file as its
"prefix file" in the "C/C++ language" settings. Disabling optional
modules (for the 68K interpreter), building non-GUSI interpreters and
various other things are accomplished by modifying these files (and
possibly changing the list of files included in the project window, of
course).
<DT> OSX
<DD> Specific to MacPython-OSX, not used by MacPython-OS9.
<DT> OSXResources
<DD> Specific to MacPython-OSX, not used by MacPython-OS9.
<DT> Python
<DD> Mac-specific parts of the core interpreter.
<DT> Resources
<DD> Resource files needed to build the interpreter.
<DT> Scripts
<DD> A collection of various mac-specific Python scripts. Some are
essential, some are useful but few are documented, so you will have to
use your imagination to work them out.
<DT> Tools
<DD> A collection of tools, usually bigger than those in the scripts
folder. The important ones here are the IDE and macfreeze. The IDE is built
with the buildIDE.py script, which puts the resulting applet in the toplevel
folder. Macfreeze is usually invoked through the BuildApplication script,
but for more control over the freezing process you can run the main script here.
<DT> Unsupported
<DD> Modules that are not supported any longer but may still work with a little effort.
</DL>
<H2>Building the PPC interpreter</H2>
First you optionally build the external libraries with buildlibs.prj. <p>
Then, the <code>fullbuild</code> script can be used to build
everything, but you need a fully-functional interpreter before you can
use it (and one that isn't rebuilt in the process: you cannot rebuild
a running program). You could copy the interpreter to a different
place and use that to run fullbuild. The <code>PythonStandSmall.prj</code>
project builds an interpreter that is suited to this, and it can also come
in handy if you need to debug things (which is easier in a static program). <p>
In case you want to build by hand, or in case the <code>fullbuild</code>
script does not work, here is a breakdown of the various projects. <p>
The projects for interpreter and core library are linked together, so
building the PythonInterpreter target
in <code>PythonInterpreter.prj</code>
will result in the whole core being built, but not the extension modules. <p>
You will get about 100 warnings on "missing prototype" for the various module init
routines, ignore these. You will also get numerous warnings on functions from GUSI which
override functions from MSL, ignore these too. <p>
Here is a breakdown of the projects:
<DL>
<DT> PythonCore
<DD> The shared library that contains the bulk of the interpreter and
its resources.
It is a good idea to immedeately put an alias to this
shared library in the <code>Extensions</code> folder of your system
folder. Do exactly that: put an <em>alias</em> there, copying or
moving the file will cause you grief later if you rebuild the library and
forget to copy it to the extensions folder again. The ConfigurePythonXXX applets
will also do this. <br>
<DT> PythonInterpeter
<DD> The interpreter. This is basically a routine to call out to the
shared library. <p>
<DT> Plugin projects
<DD> Each plugin module has a separate project, and these can be rebuilt on
the fly. Fullbuild (or actually it's little helper genpluginprojects) takes
care of this.
</DL>
After creating the alias to <code>PythonCore</code> you remove any old
<code>Python XXXX Preferences</code> file from the <code>Preferences</code> folder
(if you had python installed on your system before) and run the interpreter once
to create the correct preferences file. <p>
Next, you have to build the extension modules.
If you don't use fullbuild simply open each project and build it.
<p>
Finally, you must build the standard applets:
<code>EditPythonPrefs</code>, <code>BuildApplet</code>, etc. For the N-th time:
fullbuild does this for you, but you can also manually drag/drop them onto
BuildApplet. <p>
You are all set now, and should read the release notes and
<code>ReadMe</code> file from the <code>Mac</code> folder.
Rebuilding .exp files is no longer needed since CodeWarrior 7.
<H2><a name="cvs">Using the CVS source archive</a></H2>
It is possible (and probably best) to access the Python sources through remote CVS. The
advantage of this is that you get the very latest sources, so any bug
fixed or new features will be immedeately available. This is also the
disadvantage, of course: as this is the same tree as is used for
development it may sometimes be a little less stable. <p>
The CVS client of choice is Alexandre Parenteau's MacCVS. It can be
obtained through the <a href="http://www.wincvs.org">WinCVS
homepage</a>. MacCVS uses Internet Config to set file types correctly
based on the filename extension. In the maccvs preferences you should
also set (in the "binary files" section) "use mac encoding:
applesingle" and (in the "text files" section) "use ISO latin 1
conversion". <p>
It is a good idea to disable Quicktime Exchange in the Quicktime control
panel if you are on OS9 or before. Quicktime Exchange will magically map
some extensions to filetypes, and this can seriously hinder you if, for
instance, <code>.bmp</code> is not a Windows bitmap file. <p>
The Python sources are checked out from the main
Python CVS archive on sourceforge.net, see the <a
href="http://www.python.org/download/cvs.html">Source access via
CVS</a> page for details. When you check the sources out you will get
something like <code>Python:dist:src</code>, and under that the
<code>Modules</code>, <code>Lib</code>, <code>Mac</code> etc hierarchy. The
<code>src</code> folder can be renamed to <code>Python</code>, and
is what this document refers to as the "toplevel Python folder". <P>
The CVS repository does not contain all the projects for the plugin modules,
these are built with <code>fullbuild.py</code> normally. For this reason
it is probably a good idea to first build <code>PythonStandSmall.prj</code>,
which builds a fairly minimal interpreter, and then follow the
fullbuild instructions</a>.
<H2>Odds and ends</H2>
Some remarks that I could not fit in elsewhere:
<UL>
<LI> It may be possible to use the <code>PythonCore</code> shared
library to embed Python in another program, if your program can live
with using GUSI for I/O. Use PythonCore in stead of your MSL C library
(or, at the very least, link it before the normal C library). Ask for help
on PythonMac-SIG if you have problems with this.
<LI> <a name="extending"></a>It is possible to build PPC extension
modules without building a complete Python. The binary distribution
installer can optionally install all the needed folders (the develop
option). A template for a dynamic module can be found in
<code>xx.prj</code>.
<LI> The Python shared library architecture is a variant of the architecture
described as "application with shared libraries and dropins" in the MetroWerks
"Targeting MacOS" documentation. The Python Application and applet-template use
the <code>MSL AppRuntime.Lib</code> runtime library (with properly set CFM
initialization and termination routines). PythonCore uses <code>MSL Runtime.Lib</code>,
which is really intended for standalone programs but which we fool into working by
providing a dummy main program.
It is linked statically into PythonCore (and exported to the applications and plugins)
so we do not have to distribute yet another shared library. Plugin modules use
<code>MSL ShlibRuntime.Lib</code> (not the dropin runtime: modules are never unloaded)
and obtain the rest from PythonCore. PythonCore uses a
non-standard initialization entry point, <code>__initialize_with_resources</code>, to
be able to obtain resources from the library file later on. Plugins can do the same
(_tkinter does) or use the standard <code>__initialize</code> entry point.
</UL>
</BODY>
</HTML>

View File

@ -1,90 +0,0 @@
<HTML><HEAD><TITLE>Using python to create CGI scripts</TITLE></HEAD>
<BODY>
<H1>Using python to create CGI scripts</H1>
<HR>
In this document we will (eventually) explain how to create Python CGI scripts
for use with Personal WebServer, WebStar and probably other Mac-based HTTP servers too.
Since CGI scripts are AppleEvent servers on the mac we will also learn
a little about general AppleEvent server programming and about applet
debugging. <p>
<blockquote>Note that the current setup is very preliminary, and hence
itis probably not wise to base your strategic products on the information
in this document:-) In stead, play with the code here and join the
<a href="mailto:pythonmac-sig-request@python.org">pythonmac-sig</a>, where
we I would like to have a discussion on a real design for a Mac CGI framework
(preferrably something that will make CGI scripts portable to unix and other
platforms).
</blockquote>
<h2>AppleEvent servers</h2>
Since AppleEvent clients are easier to write and understand than servers
you should probably read the section on <a href="applescript.html">Open Scripting
clients in Python</a> first. <p>
Next, let us have a look at the AE Server framework,
<a href="../Lib/toolbox/MiniAEFrame.py">MiniAEFrame.py</a>.
This file contains two classes, <code>MiniApplication</code> and <code>AEServer</code>.
MiniApplication is a tiny replacement for <code>FrameWork.Application</code>,
suitable if your application does not need windows and such.
AEServer is a bit of glue that does part of the appleevent decoding for you. You
call <code>installaehandler</code> passing it the class and id (4-char strings)
of the event you have a handler for and the handler callback routine. When the
appleevent occurs your callback is called with the right arguments. For now,
your argument names are the 4-char values used internally by Open Scripting,
eventually there will be a translation similar to what the generated OSA client
suites provide. <p>
You can test AEServer by double-clicking it. It will react to the standard
run/open/print/quit OSA commands. If it is running as a normal python script and you
drag a file onto the interpreter the script will tell you what event it got. <p>
<h2>A Minimal CGI script</h2>
To try a CGI script you will first need a http server. Apple's Personal Webserver
is fine, but I have also used the
shareware
<a href="http://www.stairways.com/netpresenz/">NetPresenz</a>
by Peter Lewis
(don't forget to pay if you give it more than a test run!). Install your
http server, and make sure that it can serve textual documents. <p>
Next, let us have a look at our example CGI scripts. CGI scripts have to be
applications, so we will have to make an applet as explained in
<a href="example2.html">example 2</a>. Our applet code,
<a href="cgi/cgitest.cgi.py">cgitest.cgi.py</a> is a rather minimal <code>execfile</code>
statement. The reason for this is debugging: the real code is in
<a href="cgi/realcgitest.py">realcgitest.py</a>, and this way you do not have
to run mkapplet again every time you change the code. Rename realcgitest.py
to cgitest.cgi.py once you are satisfied that it works. <p>
The resource file is not very special, with one exception: since we want to do
our own appleevent handling we don't want the Python initialization code to
create argc and argv for use, since this might gobble up any appleevents we are
interested in. For this reason we have included a 'Popt' resource that disables
the argv initialization. An easy way to create this resource is to drop
the <code>.rsrc</code> file (or the finished applet, if you like) onto
<code>EditPythonPrefs</code> and set the "no argv processing" option. <p>
The code itself is actually not too complicated either. We install handlers
for "open application" and "quit" (stolen from the test code in MiniAEFrame)
and the <code>"WWW\275"/"sdoc"</code> event, the event sent on CGI execution.
The cgi handler pretty-prints the CGI arguments in HTML and returns the whole
string that is to be passed to the client. The actual parameters passed
are explained in <a href="http://www.biap.com/datapig/mrwheat/cgi_params.html">
http://www.biap.com/datapig/mrwheat/cgi_params.html</a>. <p>
To test the script drop <code>cgitest.cgi.py</code> onto <code>mkapplet</code>,
move the resulting <code>cgitest.cgi</code> to somewhere where it is reachable
by NetPresenz, and point your web browser towards it. Note that this assume you have
already renamed realcgitest.py to cgitest.cgi.py, otherwise you'll also have
to copy that file along. <p>
For Apple's Personal Webserver you need to do a bit more: you have to copy the
cgi applet to somewhere in your "Webpages" folder and you have to tell the webserver
(in the control panels) that your CGI script exists. I don't understand what the various
types of cgi scripts mean, but experiment with them.
</BODY></HTML>

View File

@ -1,2 +0,0 @@
# Debug applets quickly.
execfile('realcgitest.py')

Binary file not shown.

View File

@ -1,59 +0,0 @@
"""cgitest - A minimal CGI applet. Echos parameters back to the client.
"""
from MiniAEFrame import AEServer, MiniApplication
import MacOS
debug=1
class CGITest(AEServer, MiniApplication):
def __init__(self):
MiniApplication.__init__(self)
AEServer.__init__(self)
self.installaehandler('aevt', 'oapp', self.open_app)
self.installaehandler('aevt', 'quit', self.quit)
self.installaehandler('WWW\275', 'sdoc', self.cgihandler)
if debug:
self.installaehandler('****', '****', self.otherhandler)
oldparams = MacOS.SchedParams(0, 0)
self.mainloop()
apply(MacOS.SchedParams, oldparams)
def quit(self, **args):
self.quitting = 1
def open_app(self, **args):
pass
def otherhandler(self, *args, **kwargs):
print 'Unknown AppleEvent'
print 'args', args
print 'kwargs', kwargs
def cgihandler(self, pathargs, **args):
if debug:
print 'CGI request', pathargs, args
rv = """HTTP/1.0 200 OK
Server: Unknown; python-cgi-script
MIME-Version: 1.0
Content-type: text/html
<title>Python CGI-script results</title>
<h1>Python CGI-script results</h1>
<hr>
"""
rv = rv+'<br><b>Direct object:</b> %s\n'%pathargs
for key in args.keys():
if key[0] != '_':
rv = rv + '<br><b>%s:</b> %s\n'%(key, args[key])
rv = rv +'<hr>\nSee you next time!\n'
# Note: if you want to quit after each request enable the line
# self.quitting = 1
return rv
if __name__ == '__main__':
CGITest()

View File

@ -1,44 +0,0 @@
<HTML>
<HEAD>
<TITLE>Embedding Python on the Mac</TITLE>
</HEAD>
<BODY>
<H1>Embedding Python on the Mac</H1>
<HR>
<B>Note</B>: if you have a binary-only release of MacPython you will not
have this demo installed. Install the developer option (in the standard installer) or
a source release if you want to embed
Python in other applications. <p>
Embedding Python on the mac is pretty similar to embedding it on other
platforms, but a few points need mentioning:
<UL>
<LI> You call <CODE>PyMac_Initialize()</CODE> in stead of
<CODE>Py_Initialize()</CODE>. The prototype is in <CODE>macglue.h</CODE>.
This call initializes the toolbox, GUSI (if needed), sets up the correct
resource files and calls Py_Initialize.
<LI> You have to be consequent in your use of GUSI. If the library uses
it so should your program and vice versa.
<LI> The console-behaviour (close-on-exit, etc) is controlled by Python
but you can overwrite this with <code>PyMac_SetConsoleHandler()</code>.
</UL>
The Python environment is started with a dummy argc and argv, and initial
startup options are obtained through the usual means, except that the
user pression the option-key will not result in an interactive dialog.
You can, however, set startup options on your program in the same way as you
do for applets, by dragging your application to <code>EditPythonPrefs</code>. <p>
The most logical way to embed Python is to link it against the shared
library <code>PythonCore</code>. An example project and source can be
found in the <a href="embed">embed</a> folder. <p>
This example code also shows how to override the console: if you pass the
<code>-q</code> argument in the argument box output is thrown away. If you
pass the <code>-d</code> option the output is sent to <code>DebugStr</code>
(so be sure to use this only when running the example under a debugger).
</BODY>
</HTML>

View File

@ -1,71 +0,0 @@
/* Example of embedding Python in another program */
#include "Python.h"
#include "macglue.h"
static char *argv0;
long my_writehandler(char *buf, long count)
{
long mycount;
unsigned char mybuf[255];
mycount = count;
if (mycount > 255 ) mycount = 255;
mybuf[0] = (unsigned char)mycount;
strncpy((char *)mybuf+1, buf, mycount);
DebugStr(mybuf);
return count;
}
main(argc, argv)
int argc;
char **argv;
{
/* So the user can set argc/argv to something interesting */
argc = ccommand(&argv);
/* Save a copy of argv0 */
argv0 = argv[0];
/* If the first option is "-q" we don't open a console */
if ( argc > 1 && strcmp(argv[1], "-q") == 0 ) {
PyMac_SetConsoleHandler(PyMac_DummyReadHandler, PyMac_DummyWriteHandler,
PyMac_DummyWriteHandler);
} else
if ( argc > 1 && strcmp(argv[1], "-d") == 0 ) {
PyMac_SetConsoleHandler(PyMac_DummyReadHandler, my_writehandler,
my_writehandler);
}
/* Initialize the Python interpreter. Required. */
PyMac_Initialize();
/* Define sys.argv. It is up to the application if you
want this; you can also let it undefined (since the Python
code is generally not a main program it has no business
touching sys.argv...) */
PySys_SetArgv(argc, argv);
/* Do some application specific code */
printf("Hello, brave new world\n\n");
/* Execute some Python statements (in module __main__) */
PyRun_SimpleString("import sys\n");
PyRun_SimpleString("print sys.builtin_module_names\n");
PyRun_SimpleString("print sys.argv\n");
/* Note that you can call any public function of the Python
interpreter here, e.g. call_object(). */
/* Some more application specific code */
printf("\nGoodbye, cruel world\n");
/* Exit, cleaning up the interpreter */
Py_Exit(0);
/*NOTREACHED*/
}
/* This function is called by the interpreter to get its own name */
char *
getprogramname()
{
return argv0;
}

Binary file not shown.

View File

@ -1,151 +0,0 @@
<HTML>
<HEAD>
<TITLE>Creating standalone applications with Python</TITLE>
</HEAD>
<BODY>
<H1>Creating standalone applications with Python</H1>
With <a href="example2.html#applet">BuildApplet</a> you can build a standalone
Python application that works like
any other Mac application: you can double-click it, run it while the
Python interpreter is running other scripts, drop files on it, etc. It is, however,
still dependent on the whole Python installation on your machine: the PythonCore
engine, the plugin modules and the various Lib folders.<p>
In some cases you may want to create a true application, for instance because
you want to send it off to people who may not have Python installed on their
machine, or because you the application is important and you do not want changes
in your Python installation like new versions to influence it.
<H2>The easy way</H2>
The easiest way to create an application from a Python script is simply by dropping
it on the <code>BuildApplication</code> applet in the main Python folder.
BuildApplication has a similar interface as BuildApplet: you drop a script on
it and it will process it, along with an optional <code>.rsrc</code> file.
<P>
What BuildApplication does, however, is very different. It parses your script,
recursively looking for all modules you use, bundles the compiled code for
all these modules in PYC resources, adds the executable machine code for the
PythonCore engine, any dynamically loaded modules you use and a main program, combines
all this into a single file and adds a few preference resources (which you
can inspect with <code>EditPythonPrefs</code>, incidentally) to isolate the
new program from the existing Python installation.<P>
Usually you do not need to worry about all this, but occasionally you may have
to exercise some control over the process, for instance because your
program imports modules that don't exist (which can happen if your script
is multi-platform and those modules will never be used on the Mac). See
the section on <a href="#directives">directives</a> below for details.
If you get strange error messages about missing modules it may also be worthwhile
to run macfreeze in report mode on your program, see below.
<P>
<H2>Doing it the hard way</H2>
With the <EM>macfreeze</EM> script, for which BuildApplication is a simple
wrapper, you can go a step further and create CodeWarrior projects and
sourcefiles which can then be used to build your final application. While
BuildApplication is good enough for 90% of the use cases there are situations
where you need macfreeze itself, mainly if you want to embed your frozen Python
script into an existing C application, or when you need the extra bit of speed:
the resulting application will start up a bit quicker than one generated
with BuildApplication. <p>
When you start
<code>Mac:Tools:macfreeze:macfreeze.py</code> you are asked for the
script file, and you can select which type of freeze to do. The first
time you should always choose <em>report only</em>, which will produce a
listing of modules and where they are included from in the console
window. Macfreeze actually parses all modules, so it may crash in the
process. If it does try again with a higher debug value, this should
show you where it crashes. <p>
<h2><a name="directives">Directives</a></h2>
For more elaborate programs you will often see that freeze includes
modules you don't need (because they are for a different platform, for
instance) or that it cannot find all your modules (because you modify
<code>sys.path</code> early in your initialization). It is possible to
include directives to tell macfreeze to add items to the search path and
include or exclude certain modules. All your directives should be in the
main script file. <p>
Directives have the following form:
<pre>
# macfreeze: command argument
</pre>
The trigger <code>macfreeze:</code> must be spelled exactly like that,
but the whitespace can be any combination of spaces and tabs. Macfreeze
understands the following directives:
<DL>
<DT> <code>path</code>
<DD> Prepend a folder to <code>sys.path</code>. The argument is a
pathname, which should probably be relative (starting with a colon) and
is interpreted relative to the folder where the script lives.
<DT> <code>include</code>
<DD> Include a module. The module can either be given by filename or by
module name, in which case it is looked up through the normal method.
<DT> <code>exclude</code>
<DD> Exclude a module. The module must be given by modulename. Even when
freeze deems the module necessary it will not be included in the
application.
<DT> <code>optional</code>
<DD> Include a module if it can be found, but don't complain if it can't.
</DL>
There is actually a fourth way that macfreeze can operate: it can be used
to generate only the resource file containing the compiled <code>PYC</code>
resources. This may be useful if you have embedded Python in your own
application. The resource file generated is the same as for the CodeWarrior
generation process. <p>
<h2>Freezing with CodeWarrior</h2>
To freeze with CodeWarrior you need CodeWarrior, obviously, and a full
source distribution of Python. You select the <em>Codewarrior source and
project</em> option. You specify an output folder, which is by default
the name of your script with <code>.py</code> removed and
<code>build.</code> prepended. If the output folder does not exist yet
it is created, and a template project file and bundle resource file are
deposited there. Next, a source file <code>macfreezeconfig.c</code> is
created which includes all builtin modules your script uses, and a
resource file <code>frozenmodules.rsrc</code> which contains the
<code>PYC</code> resources for all your Python modules. <p>
The project expects to live in a folder one level below the Python root
folder, so the next thing you should do is move the build folder there.
It is a good idea to leave an alias with the same name in the original
location: when you run freeze again it will regenerate the
<code>frozenmodules.rsrc</code> file but not the project and bundle
files. This is probably what you want: if you modify your python sources
you have to re-freeze, but you may have changed the project and bundle
files, so you don't want to regenerate them. <p>
An alternative is to leave the build folder where it is, but then you
have to adapt the search path in the project. <p>
The project is set up to include all the standard builtin modules, but
the CW linker is smart enough to exclude any object code that isn't
referenced. Still, it may be worthwhile to remove any sources for
modules that you are sure are not used to cut back on compilation time.
You may also want to examine the various resource files (for Tcl/Tk, for
instance): the loader has no way to know that these aren't used. <p>
You may also need to add sourcefiles if your script uses non-standard
builtin modules, like anything from the <code>Extensions</code> folder. <p>
The <code>frozenbundle.rsrc</code> resource file contains the bundle
information. It is almost identical to the bundle file used for applets,
with the exception that it sets the <code>sys.path</code> initialization
to <code>$(APPLICATION)</code> only. This means that all modules will only
be looked for in PYC resources in your application. <p>
</BODY>
</HTML>

View File

@ -1,97 +0,0 @@
/*
** InterslipLib - Routines to talk to InterSLIP. Version 1.1, 31-Oct-1995.
**
**
** (c) Jack Jansen, CWI, 1995 <jack@cwi.nl>
*/
#include <Devices.h>
#include "InterslipLib.h"
static CntrlParam iopb;
static short refnum = -1;
OSErr is_open()
{
if ( refnum >= 0 ) return 0;
return OpenDriver("\p.InterSLIP", &refnum);
}
OSErr is_connect()
{
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 2;
return PBControlImmed((ParmBlkPtr)&iopb);
}
OSErr is_disconnect()
{
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 3;
return PBControlImmed((ParmBlkPtr)&iopb);
}
OSErr is_status(long *status, long *msgseqnum, StringPtr *msg)
{
long *csp;
OSErr err;
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 4;
if( err = PBControlImmed((ParmBlkPtr)&iopb) )
return err;
csp = (long *)&iopb.csParam;
*status = csp[0];
*msgseqnum = csp[1];
*msg = (unsigned char *)csp[2];
return 0;
}
OSErr is_getconfig(long *baudrate, long *flags,
Str255 idrvnam, Str255 odrvnam, Str255 cfgnam)
{
long *csp;
OSErr err;
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 6;
csp = (long *)&iopb.csParam;
csp[2] = (long)idrvnam;
csp[3] = (long)odrvnam;
csp[4] = (long)cfgnam;
if( err = PBControlImmed((ParmBlkPtr)&iopb) )
return err;
*baudrate = csp[0];
*flags = csp[1];
return 0;
}
OSErr is_setconfig(long baudrate, long flags,
Str255 idrvnam, Str255 odrvnam, Str255 cfgnam)
{
long *csp;
OSErr err;
iopb.ioCRefNum = refnum;
iopb.ioVRefNum = refnum;
iopb.ioCompletion = (UniversalProcPtr) 0;
iopb.csCode = 7;
csp = (long *)&iopb.csParam;
csp[0] = baudrate;
csp[1] = flags;
csp[2] = (long)idrvnam;
csp[3] = (long)odrvnam;
csp[4] = (long)cfgnam;
return PBControlImmed((ParmBlkPtr)&iopb);
}

View File

@ -1,20 +0,0 @@
/*
** InterSLIP API.
*/
#include <Types.h>
/* States */
#define IS_IDLE 0
#define IS_WMODEM 1
#define IS_DIAL 2
#define IS_LOGIN 3
#define IS_RUN 4
#define IS_DISC 5
OSErr is_open(); /* Open InterSLIP driver (optional) */
OSErr is_connect();/* Connect */
OSErr is_disconnect(); /* Disconnect */
OSErr is_status(long *, long *, StringPtr *); /* Get status, msg seq#, msg pointer */
OSErr is_getconfig(long *, long *, Str255 , Str255 , Str255 ); /* get config */
OSErr is_setconfig(long , long , Str255 , Str255 , Str255 ); /* set config */

View File

@ -1,225 +0,0 @@
/***********************************************************
Copyright 1991-1995 by Stichting Mathematisch Centrum, Amsterdam,
The Netherlands.
All Rights Reserved
Permission to use, copy, modify, and distribute this software and its
documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
both that copyright notice and this permission notice appear in
supporting documentation, and that the names of Stichting Mathematisch
Centrum or CWI not be used in advertising or publicity pertaining to
distribution of the software without specific, written prior permission.
STICHTING MATHEMATISCH CENTRUM DISCLAIMS ALL WARRANTIES WITH REGARD TO
THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
FITNESS, IN NO EVENT SHALL STICHTING MATHEMATISCH CENTRUM BE LIABLE
FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
******************************************************************/
#include "Python.h"
#include "InterslipLib.h"
#include "macglue.h"
static PyObject *ErrorObject;
/* ----------------------------------------------------- */
static char pyis_open__doc__[] =
"Load the interslip driver (optional)"
;
static PyObject *
pyis_open(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_open();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static char pyis_connect__doc__[] =
"Tell the driver to start a connect"
;
static PyObject *
pyis_connect(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_connect();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static char pyis_disconnect__doc__[] =
"Tell the interslip driver to start a disconnect"
;
static PyObject *
pyis_disconnect(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_disconnect();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
static char pyis_status__doc__[] =
"Return (numeric_status, message_seqnum, message_string) status tuple"
;
static PyObject *
pyis_status(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
long status, seqnum;
StringPtr message;
OSErr err;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_status(&status, &seqnum, &message);
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
return Py_BuildValue("iiO&", (int)status, (int)seqnum, PyMac_BuildStr255, message);
}
static char pyis_getconfig__doc__[] =
"Return configuration data (ibaud, obaud, flags, idrvname, odrvname, cfgname)"
;
static PyObject *
pyis_getconfig(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
long baudrate, flags;
Str255 idrvname, odrvname, cfgname;
OSErr err;
int ibaud, obaud;
if (!PyArg_ParseTuple(args, ""))
return NULL;
err = is_getconfig(&baudrate, &flags, idrvname, odrvname, cfgname);
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
ibaud = (baudrate >> 16) & 0xffff;
obaud = baudrate & 0xffff;
return Py_BuildValue("iiiO&O&O&", ibaud, obaud, (int)flags, PyMac_BuildStr255, idrvname,
PyMac_BuildStr255, odrvname, PyMac_BuildStr255, cfgname);
}
static char pyis_setconfig__doc__[] =
"Set configuration data (ibaud, obaud, flags, idrvname, odrvname, cfgname)"
;
static PyObject *
pyis_setconfig(self, args)
PyObject *self; /* Not used */
PyObject *args;
{
long baudrate;
int flags;
Str255 idrvname, odrvname, cfgname;
OSErr err;
int ibaud, obaud;
if (!PyArg_ParseTuple(args, "iiiO&O&O&", &ibaud, &obaud, &flags, PyMac_GetStr255, idrvname,
PyMac_GetStr255, odrvname, PyMac_GetStr255, cfgname))
return NULL;
baudrate = (ibaud << 16) | obaud;
err = is_setconfig(baudrate, (long)flags, idrvname, odrvname, cfgname);
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
Py_INCREF(Py_None);
return Py_None;
}
/* List of methods defined in the module */
static struct PyMethodDef pyis_methods[] = {
{"open", pyis_open, 1, pyis_open__doc__},
{"connect", pyis_connect, 1, pyis_connect__doc__},
{"disconnect", pyis_disconnect, 1, pyis_disconnect__doc__},
{"status", pyis_status, 1, pyis_status__doc__},
{"getconfig", pyis_getconfig, 1, pyis_getconfig__doc__},
{"setconfig", pyis_setconfig, 1, pyis_setconfig__doc__},
{NULL, NULL} /* sentinel */
};
/* Initialization function for the module (*must* be called initinterslip) */
static char interslip_module_documentation[] =
""
;
void
initinterslip()
{
PyObject *m, *d;
/* Create the module and add the functions */
m = Py_InitModule4("interslip", pyis_methods,
interslip_module_documentation,
(PyObject*)NULL,PYTHON_API_VERSION);
/* Add some symbolic constants to the module */
d = PyModule_GetDict(m);
ErrorObject = PyString_FromString("interslip.error");
PyDict_SetItemString(d, "error", ErrorObject);
/* XXXX Add constants here */
PyDict_SetItemString(d, "IDLE", PyInt_FromLong(IS_IDLE));
PyDict_SetItemString(d, "WMODEM", PyInt_FromLong(IS_WMODEM));
PyDict_SetItemString(d, "DIAL", PyInt_FromLong(IS_DIAL));
PyDict_SetItemString(d, "LOGIN", PyInt_FromLong(IS_LOGIN));
PyDict_SetItemString(d, "RUN", PyInt_FromLong(IS_RUN));
PyDict_SetItemString(d, "DISC", PyInt_FromLong(IS_DISC));
/* Check for errors */
if (PyErr_Occurred())
Py_FatalError("can't initialize module interslip");
}

View File

@ -1,484 +0,0 @@
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<HTML>
<HEAD>
<TITLE>HOWTO: Compiling Python Modules with MPW</TITLE>
</HEAD>
<BODY>
<H1>HOWTO: Compiling Python Modules with MPW</H1>
<blockquote>
This HOWTO is a slightly reformatted version of an original by
<A HREF="mailto:cwebster@nevada.edu">Corran Webster</A>, whose
<A HREF="http://www.nevada.edu/~cwebster/Python/">Python page</A>
may contain a more up-to-date version.
</blockquote>
<HR>
<P>
The <A HREF="http://www.cwi.nl/~jack/macpython.html">Macintosh version</A>
of the <A HREF="http://www.python.org/">Python programming language</A> is
usually compiled with <A HREF="http://www.metrowerks.com/">Metrowerks
CodeWarrior</A>. As a result, C extension modules are also usually
compiled with CodeWarrior, and the documentation and sample code reflects
this. CodeWarrior is a commercial product, and may be beyond the budgets
of hobbyist hackers, making them dependent on others to compile C extension
modules. At the present time, many standard C extension modules compile
"out of the box" on the Macintosh, but in only a few cases is the plugin
for the Macintosh included in the distribution.
</P>
<P>
The <A HREF="http://developer.apple.com/tools/mpw-tools/">Macintosh
Programmer's Workshop</A> (MPW) is Apple's development environment, and is
freely available for <A
HREF="ftp://ftp.apple.com/developer/Tool_Chest/Core_Mac_OS_Tools/MPW_etc./">download</A>
from Apple, as well as on their Developer CDs. Since Python was originally
developed using MPW, before CodeWarrior became the dominant MacOS
development environment, most of the idiosyncrasies of MPW are already
supported, and compilation of C extension modules in MPW is possible.
</P>
<P>
This HOWTO only deals with compiling for PowerPC Macintoshes. The process
should be similar for 68k Macintoshes using the code fragment manager, but
I have not attempted this - my old Mac is running NetBSD.
</P>
<P>
This way of compiling modules is still experimental. Please read the
caveats section below.
</P>
<H2><A NAME="setup">Setting Up MPW for Compiling Python Modules</A></H2>
<P>
This assumes that you have successfully installed both MPW and Python with
the Developer's Kit on your Macintosh.
</P>
<P>
The first step is to let MPW know where you keep Python. This step is not
strictly necessary, but will make development easier and improve
portability. Create a new file in the <CODE>Startup Items</CODE> folder of
MPW called <A HREF="Python"><CODE>Python</CODE></A>. Type the lines:
</P>
<PRE>
set Python "Macintosh HD:Applications:Python 1.5.2c1:"
set PythonIncludes "{Python}Include"
set PythonMacIncludes "{Python}Mac:Include"
set PythonCore "{Python}PythonCore"
export Python PythonIncludes PythonMacIncludes PythonCore
</PRE>
<P>
where <CODE>Macintosh HD:Applications:Python 1.5.2c1:</CODE> is replaced by
the path to the directory where you keep your copy of Python, and the other
variables reflect where you keep your header files and Python core files.
The locations here are the standard for Python 1.5.2c1, but they are
different for Python 1.52b2 and earlier (most notably, the PythonCore is
kept in the Extensions folder).
</P>
<P>
Next, you need to update the <A HREF="config.h"><CODE>config.h</CODE></A>
file for the <CODE>MrC</CODE> compiler included with MPW. This header file
is located in the <CODE>:Mac:Include</CODE> folder in the standard
distribution. You can update it by hand, by adding the lines:
</P>
<PRE>
#ifdef __MRC__
#define BAD_STATIC_FORWARD
#endif
</PRE>
<P>
at the after the similar defines for <CODE>__MWERKS__</CODE> and
<CODE>__SC__</CODE> in the file. This step is critical: many modules,
including ones in the standard distribution, will not compile properly
without this modification (see common problems below).
</P>
<P>
Copies of both the <A HREF="Python"><CODE>Python</CODE></A> startup item
for MPW and the <A HREF="config.h"><CODE>config.h</CODE></A> are included
here for your convenience.
</P>
<P>
If you are porting Unix modules to the mac, you may find it useful to
install <A
HREF="http://www.iis.ee.ethz.ch/~neeri/macintosh/gusi-qa.html">GUSI</A> for
your copy of MPW. GUSI provides some amount of POSIX compatibility, and is
used by Python itself for this purpose - at the very least having it's
header files available may be useful. Also of note for people porting Unix
modules, the most recent alpha version (4.1a8) of <CODE>MrC</CODE> and
<CODE>MrCpp</CODE> at this writing permits using unix-style pathnames for
includes via the <CODE>-includes unix</CODE> command line option. I have
not experimented heavily with this, but will be doing so in the future and
report my findings.
</P>
<P>
You now have MPW and Python set up to allow compilation of modules.
</P>
<H2><A NAME="compiling">Compiling a Module</A></H2>
<P>
This assumes that you have a C extension module ready to compile. For
instructions on how to write a module, see the Python documentation.
</P>
<P>
There are three approaches you can take to compiling in MPW: using the
command line interface, using the MPW <CODE>CreateMake</CODE> command
(available as the "Create build commands..." menu item, and writing a
Makefile by hand.
</P>
<P>
Before you start any of these, you'll need to know:
</P>
<UL>
<LI>The names and locations of the C source files. In the examples, this
is the file <A HREF="xxmodule.c"><CODE>xxmodule.c</CODE></A>, and is in
MPW's current working directory.
<LI>The name that Python expects to import your module under. In the
examples, this is <CODE>xx</CODE>, so the shared library file will be
called <CODE>xx.ppc.slb</CODE>.
<LI>The location of any additional header files use by the C source. The
example does not use any additional header files.
<LI>The location of any additional shared libraries which the module needs
to link to. The example does not link to any other shared libraries.
<LI>The name of the entry point to your module. This is usually the last
function in the main C source file, and the name usually starts with
<CODE>init</CODE>. In the examples, this is <CODE>initxx</CODE>.
</UL>
<H3>Using the Command Line</H3>
<P>
For simple modules consisting of one or two C files, it's often convenient
to simply use commands in a MPW Worksheet. Usually you will want to set
MPW's working directory to the directory containing the C source code. The
following commands compile and link the standard Python test module <A
HREF="xxmodule.c"><CODE>xxmodule.c</CODE></A>:
</P>
<PRE>
MrC "xxmodule.c" -o "xx.c.x" -w off -d HAVE_CONFIG_H &#8706;
-i "{PythonMacIncludes}" &#8706;
-i "{PythonIncludes}"
PPCLink &#8706;
-o "xx.ppc.slb" &#8706;
"xx.c.x" &#8706;
-t 'shlb' &#8706;
-c 'Pyth' &#8706;
-xm s &#8706;
-d &#8706;
"{PythonCore}" &#8706;
"{SharedLibraries}InterfaceLib" &#8706;
"{SharedLibraries}MathLib" &#8706;
"{SharedLibraries}StdCLib" &#8706;
"{PPCLibraries}StdCRuntime.o" &#8706;
"{PPCLibraries}PPCCRuntime.o" &#8706;
"{PPCLibraries}PPCToolLibs.o" &#8706;
-export initxx
</PRE>
<P>
(Note: The last character on each line should appear as "partial
derivative" symbol, which you type as <KBD>option-d</KBD> and which is
MPW's line continuation symbol.)
</P>
<P>
Any additional header files should be specified by adding their directories
as extra <CODE>-i</CODE> options to the <CODE>MrC</CODE> command. Any
additional shared libraries should be added before the PythonCore library
in the <CODE>PPCLink</CODE> command.
</P>
<P>
If there is more than one source file, you will need to duplicate the
compile command for each source file, and you will need to include all the
object files in the place where <CODE>"xx.c.x"</CODE> appears in the
<CODE>PPCLink</CODE> command.
</P>
<H3>Using CreateMake</H3>
<P>
For more complex modules, or modules that you are writing yourself, you
will probably want to use a makefile. Unfortunately MPW's makefiles are
incompatible with the standard Unix makefiles, so you will not be able to
use any makefiles which come with a C module.
</P>
<P>
Usually, you will want the makefile to reside in the same directory as the
C source code, so you should set MPW's working directory to that directory
before proceeding.
</P>
<P>
To create a makefile for the standard Python test module <A
HREF="xxmodule.c"><CODE>xxmodule.c</CODE></A>:
</P>
<UL>
<LI>Select "Create build commands..." from the "Build" Menu.
<LI>Type <KBD>xx.ppc.slb</KBD> for the Program Name.
<LI>Select "Shared Library" for the Program Type.
<LI>Select "PowerPC Only" for the Target.
<LI>Click on the "Source Files..." button, and add your module's C source
files to the list.
<LI>Click on the "Other Options..." button and change the creator type to
"Pyth". If you are using additional header files, you can also add their
directories at this stage. Click on "Continue" once you have done this.
<LI>Click on the "Exported Symbols..." button and type <KBD>initxx</KBD>
into the entry field. Click on "Continue" once you have done this.
<LI>At this stage, your CreateMake window should look like this: <IMG
SRC="html.icons/createmake.png" ALT="[picture of commando window for CreateMake]">
<LI>Click on the "CreateMake" button.
</UL>
<P>
You will now need to edit the makefile that was just created. Open the
file "xx.ppc.slb.make" in the current directory and make the following
changes:
</P>
<UL>
<LI>Change the line
<PRE>
Includes =
</PRE>
<P>
to read
</P>
<PRE>
Includes = -i "{PythonIncludes}" -i "{PythonMacIncludes}"
</PRE>
<P>
If you have any additional headers than need to be included, you can add
them here as well.
<LI>Change the line
<PRE>
PPCCOptions = {Includes} {Sym&#8226;PPC}
</PRE>
<P>
to read
</P>
<PRE>
PPCCOptions = -w off -d HAVE_CONFIG_H {Includes} {Sym&#8226;PPC}
</PRE>
<P>
<LI>After the line
<PRE>
-xm s &#8706;
</PRE>
<P>
add
</P>
<PRE>
-d &#8706;
"{PythonCore}" &#8706;
</PRE>
<P>
If you have any other shared libraries you need to link to, add each on a
line before PythonCore, terminating each line with a <CODE>&#8706;</CODE>.
</P>
</UL>
<P>Save the file. You are now ready to build.
</P>
<P>
Go to the "Build" or "Full Build" menu items, type in
<KBD>xx.ppc.slb</KBD>, and MPW should take things from there. Any time you
need to rebuild the shared library, you can simply do another "Build" or
"Full Build".
</P>
<H3>Writing a Makefile by Hand</H3>
<P>
For modules which have complex interdependencies between files, you will
likely need a more sophisticated makefile than the one created by
<CODE>CreateMake</CODE>. You will need to be familiar with the MPW
makefile format, but you can get a start by either using
<CODE>CreateMake</CODE> to get a simple starting point, or taking another
MPW makefile as a starting point.
</P>
<P>
It is beyond the scope of this HOWTO to go into the generalities of MPW
makefiles. Documentation on MPW's <CODE>Make</CODE> command can be found
with the MPW distribution, in particular the documents <A
HREF="http://developer.apple.com/tools/mpw-tools/books.html#Building">Building
and Maintaining Programs with MPW (2nd Edition)</A> and the <A
HREF="http://developer.apple.com/tools/mpw-tools/books.html#CommandRef">MPW
Command Reference</A>.
</P>
<P>
There are a couple of important points to keep in mind when writing a
makefile by hand:</P>
<UL>
<LI>When there are multiple symbols with the same name in object files or
shared libraries, <CODE>PPCLink</CODE> used the symbol from the file which
appears first in arguments of the <CODE>PPCLink</CODE> command. For this
reason, you will usually want the PythonCore and any other shared libraries
which are not part of the standard MPW runtime environment to appear before
the standard runtime libraries. This is particularly the case with
StdCLib. The "-d" option turns off the (often copious) warnings about
multiply defined symbols.
<LI>You will want to make sure that the <CODE>HAVE_CONFIG_H</CODE>
preprocessor symbol is defined for most C source files using the <CODE>-d
HAVE_CONFIG_H</CODE> option to <CODE>MrC</CODE>.
</UL>
<P>
The file <A HREF="xx.ppc.slb.make.sit.hqx"><CODE>xx.ppc.slb.make</CODE></A>
is included here for you to use as a starting point.
</P>
<H2><A NAME="using">Using the Extension Module</A></H2>
<P>
Once you have compiled your extension module, you will need to let Python
know where it is. You can either move it into a place on Python's search
path - such as the <CODE>:Mac:Plugins</CODE> folder - or modify the path to
include the location of your new module using the
<CODE>EditPythonPrefs</CODE> applet.
</P>
<P>
Your work may not be completely done, as many extension modules have a
Python wrapper around them. If the Python was not written with portability
in mind, you may need to do some more work to get that up and running.
Indeed, if the Python part uses OS-specific features, like pipes, you may
have to completely rewrite it if you can make it work at all.
</P>
<H2><A NAME="problems">Common Problems</A></H2>
<P>
There are a couple of common problems which occur when porting a module
from another platform. Fortunately, they are often easy to fix.
</P>
<H3>Static Forward Definitions</H3>
<P>
If you get a compiler error which looks something like:
</P>
<PRE>
File "xxmodule.c"; line 135 #Error: 'Xxo_Type' is already defined
</PRE>
<P>
then most likely either you have not set up <CODE>config.h</CODE> correctly
to handle static forward definitions, or the module author has not adhered
to the standard python conventions. If the second is the case, find where
the variable is first defined, and replace the <CODE>static</CODE> with
<CODE>staticforward</CODE>. Then find the second place it is defined
(usually the line where the compiler complained) and replace
<CODE>static</CODE> with <CODE>statichere</CODE>.
</P>
<P>
If you have set up things correctly, you should now be able to compile.
</P>
<H3>Automatic Type Conversion</H3>
<P>
<CODE>MrC</CODE> seems to be a little pickier about automatically
converting from one type to another than some other C compilers. These can
often be fixed by simply adding an explicit cast to the desired type.
</P>
<P>
XXX There may be a compiler option which relaxes this. That would be a
better solution.
</P>
<H2><A NAME="caveats">Caveats</A></H2>
<P>
As Jack Jansen pointed out on the Mac Python mailing list, there could
potentially be conflicts between the MetroWerks C runtime which the Python
core and standard modules was compiled with, and the MPW C runtime which
your extension module is compiled with. While things seem to work fine in
everyday use, it is possible that there are bugs which have not been
discovered yet. Most likely these world take the form of standard C
functions (most likely I/O functions due to conflicts between the SIOUX
libraries and the SIOW libraries) not working as they are supposed to, or
memory leaks caused by improper malloc/free.
</P>
<P>
Some such problems have been demonstrated by compiling modules with
PythonCore linked after StdCLib - printf does not work properly in this
setup, and I suspect that there will also be malloc/free problems in
situations where the module allocates memory which is later disposed of by
Python, or vice-versa. Compiling with PythonCore taking precedence over
StdCLib seems to give the correct behaviour.
</P>
<P>
This method of compiling should be considered experimental for the time
being. <STRONG>Use it at your own risk.</STRONG>
</P>
<P>
If you notice any quirks in modules compiled this way, or have insight into
what may go wrong or right with this situation, <A
HREF="mailto:cwebster@nevada.edu">please contact me</A> so that I can add
it to the HOWTO.
</P>
<P>
The ideal solution to this problem would be to get Python to compile using
MPW (and a Python MPW Tool would be very neat indeed). However, that does
seem to be a major project.
</P>
<DIV class=footer>
<HR>
<BR>
&copy;<A HREF="mailto:cwebster@nevada.edu">Corran Webster</A>, 1999. <BR>
<!-- #LASTMODIFIED TEXT="Last modified" FORM="SHORT,TIME" -->
Last modified 14/12/99 12:17 PM
<!-- /#LASTMODIFIED -->
</DIV>
</BODY>
</HTML>

View File

@ -1,324 +0,0 @@
<HTML><HEAD><TITLE>Creating a C extension module on the Macintosh</TITLE></HEAD>
<BODY>
<H1>Creating a C extension module on the Macintosh</H1>
<HR>
This document gives a step-by-step example of how to create a new C
extension module on the mac. For this example, we will create a module
to interface to the programmers' API of InterSLIP, a package that
allows you to use MacTCP (and, hence, all internet services) over a
modem connection. The actual example does not work anymore, as both
MacTCP and Interslip died long ago, but the text is still mostly
correct.<p>
<H2>Prerequisites</H2>
There are a few things you need to pull this off. First and foremost,
you need a C development environment. Actually, you need a specific
development environment, CodeWarrior by <A
HREF="http://www.metrowerks.com/">MetroWerks</A>. You will
need Version 7 or later. You may be able to get by with an older
version of CodeWarrior or with another development environment (Up to
about 1994 python was developed with THINK C, and in the dim past it
was compiled with MPW C) assuming you have managed to get Python to
compile under your development environment, but the step-by-step
character of this document will be lost. <p>
Next, you need to install the Developer option in the MacPython installer.
You may also find that Guido's <A
HREF="http://www.python.org/doc/ext/ext.html">Extending and embedding
the Python interpreter</A> is a very handy piece of documentation. I
will skip lots of details that are handled there, like complete
descriptions of <CODE>Py_ParseTuple</CODE> and such utility routines, or
the general structure of extension modules. <p>
<H2>InterSLIP and the C API to it</H2>
InterSLIP, the utility to which we are going to create a python
interface, is a system extension that does all the work of connecting
to the internet over a modem connection. InterSLIP is provided
free-of-charge by <A
HREF="http://www.intercon.com/">InterCon</A>. First it connects to
your modem, then it goes through the whole process of dialling,
logging in and possibly starting the SLIP software on the remote
computer and finally it starts with the real work: packing up IP
packets handed to it by MacTCP and sending them to the remote side
(and, of course, the reverse action of receiving incoming packets,
unpacking them and handing them to MacTCP). InterSLIP is a device
driver, and you control it using a application supplied with it,
InterSLIP Setup. The API that InterSLIP Setup uses to talk to the
device driver is published in the documentation and, hence, also
useable by other applications. <p>
I happened to have a C interface to the API, which is all ugly
low-level device-driver calls by itself. The C interface is in <A
HREF="interslip/InterslipLib.c">InterslipLib.c</A> and <A
HREF="interslip/InterslipLib.h">InterslipLib.h</A>, we'll
concentrate here on how to build the Python wrapper module around
it. Note that this is the "normal" situation when you are writing a
Python extension module: you have some sort of functionality available
to C programmers and want to make a Python interface to it. <p>
<H2>Using Modulator</H2>
The method we describe in this document, using Modulator, is the best
method for small interfaces. For large interfaces there is another
tool, Bgen, which actually generates the complete module without you
lifting a single finger. Bgen, however, has the disadvantage of having
a very steep learning curve, so an example using it will have to wait
until another document, when I have more time. <p>
First, let us look at the <A
HREF="interslip/InterslipLib.h">InterslipLib.h</A> header file,
and see that the whole interface consists of six routines:
<CODE>is_open</CODE>, <CODE>is_connect</CODE>,
<CODE>is_disconnect</CODE>, <CODE>is_status</CODE>,
<CODE>is_getconfig</CODE> and <CODE>is_setconfig</CODE>. Our first
step will be to create a skeleton file <A
HREF="interslip/@interslipmodule.c">@interslipmodule.c</A>, a
dummy module that will contain all the glue code that python expects
of an extension module. Creating this glue code is a breeze with
modulator, a tool that we only have to tell that we want to create a
module with methods of the six names above and that will create the
complete skeleton C code for us. <p>
Why call this dummy module <CODE>@interslipmodule.c</CODE> and not
<CODE>interslipmodule.c</CODE>? Self-preservation: if ever you happen
to repeat the whole process after you have actually turned the
skeleton module into a real module you would overwrite your
hand-written code. By calling the dummy module a different name you
have to make <EM>two</EM> mistakes in a row before you do this. <p>
If you installed Tk support when you installed Python this is extremely
simple. You start modulator and are provided with a form in which you
fill out the details of the module you are creating. <p>
<IMG SRC="html.icons/modulator.gif" ALIGN=CENTER><p>
You'll need to supply a module name (<CODE>interslip</CODE>, in our
case), a module abbreviation (<CODE>pyis</CODE>, which is used as a
prefix to all the routines and data structures modulator will create
for you) and you enter the names of all the methods your module will
export (the list above, with <CODE>is_</CODE> stripped off). Note that
we use <CODE>pyis</CODE> as the prefix instead of the more logical
<CODE>is</CODE>, since the latter would cause our routine names to
collide with those in the API we are interfacing to! The method names
are the names as seen by the python program, and the C routine names
will have the prefix and an underscore prepended. Modulator can do
much more, like generating code for objects and such, but that is a
topic for a later example. <p>
Once you have told modulator all about the module you want to create
you press "check", which checks that you haven't omitted any
information and "Generate code". This will prompt you for a C output
file and generate your module for you. <p>
<H2>Using Modulator without Tk</H2>
Modulator actually uses a two-stage process to create your code: first
the information you provided is turned into a number of python
statements and then these statements are executed to generate your
code. This is done so that you can even use modulator if you don't
have Tk support in Python: you'll just have to write the modulator
python statements by hand (about 10 lines, in our example) and
modulator will generate the C code (about 150 lines, in our
example). Here is the Python code you'll want to execute to generate
our skeleton module: <p>
<CODE><PRE>
import addpack
addpack.addpack('Tools')
addpack.addpack('modulator')
import genmodule
m = genmodule.module()
m.name = 'interslip'
m.abbrev = 'pyis'
m.methodlist = ['open', 'connect', 'disconnect', 'status', \
'getconfig', 'setconfig']
m.objects = []
fp = open('@interslipmodule.c', 'w')
genmodule.write(fp, m)
</PRE></CODE>
Drop this program on the python interpreter and out will come your
skeleton module. <p>
Now, rename the file to interslipmodule.c and you're all set to start
developing. The module is complete in the sense that it should
compile, and that if you import it in a python program you will see
all the methods. It is, of course, not yet complete in a functional
way... <p>
<H2>Creating a plugin module</H2>
The easiest way to build a plugin module is to use the distutils package,
this works fine on MacOS with CodeWarrior. See the distutils documentation
for details. Keep in mind that even though you are on the Mac you specify
filenames with Unix syntax: they are actually URLs, not filenames.
<p>
Alternatively you can build the project file by hand.
Go to the ":Mac:Build" folder and copy the files xx.carbon.mcp,
and xx.carbon.mcp.exp to interslipmodule.carbon.mcp and
interslipmodule.carbon.mcp.exp, respectively. Edit
interslipmodule.carbon.mcp.exp and change the name of the exported routine
"initxx" to "initinterslip". Open interslipmodule.carbon.mcp with CodeWarrior,
remove the file xxmodule.c and add interslipmodule.c and make a number
of adjustments to the preferences:
<UL>
<LI> in PPC target, set the output file name to "interslipmodule.carbon.slb",
<LI> if you are working without a source distribution (i.e. with a normal
binary distribution plus a development distribution) you will not have
a file <code>PythonCoreCarbon</code>. The installation process has deposited this
file in the System <code>Extensions</code> folder under the name
<code>PythonCoreCarbon <i>version</i></code>. Add that file to the project, replacing
<code>PythonCoreCarbon</code>.
<LI> you must either download and build GUSI (if your extension module uses sockets
or other Unix I/O constructs) or remove GUSI references from the Access Paths
settings. See the <a href="building.html">Building</a> document for where to get GUSI
and how to build it.
</UL>
Next, compile and link your module, fire up python and test it. <p>
<H2>Getting the module to do real work</H2>
So far, so good. In half an hour or so we have created a complete new
extension module for Python. The downside, however, is that the module
does not do anything useful. So, in the next half hour we will turn
our beautiful skeleton module into something that is at least as
beautiful but also gets some serious work done. For this once,
<EM>I</EM> have spent that half hour for you, and you can see the
results in <A
HREF="interslip/interslipmodule.c">interslipmodule.c</A>. <p>
We add
<CODE><PRE>
#include "InterslipLib.h"
#include "macglue.h"
</PRE></CODE>
to the top of the file, and work our way through each of the methods
to add the functionality needed. Starting with open, we fill in the
template docstring, the value accessible from Python by looking at
<CODE>interslip.open.__doc__</CODE>. There are not many tools using
this information at the moment, but as soon as class browsers for
python become available having this minimal documentation available is
a good idea. We put "Load the interslip driver" as the comment
here. <p>
Next, we tackle the body of <CODE>pyis_open()</CODE>. Since it has no
arguments and no return value we don't need to mess with that, we just
have to add a call to <CODE>is_open()</CODE> and check the return for
an error code, in which case we raise an error:
<CODE><PRE>
err = is_open();
if ( err ) {
PyErr_Mac(ErrorObject, err);
return NULL;
}
</PRE></CODE>
The routine <CODE><A NAME="PyErr_Mac">PyErr_Mac()</A></CODE> is a
useful routine that raises the exception passed as its first
argument. The data passed with the exception is based on the standard
MacOS error code given, and PyErr_Mac() attempts to locate a textual
description of the error code (which sure beats the "error -14021"
messages that so many macintosh applications tell their poor
users). <p>
We will skip pyis_connect and pyis_disconnect here, which are pretty
much identical to pyis_open: no arguments, no return value, just a
call and an error check. With pyis_status() things get interesting
again: this call still takes 3 arguments, and all happen to be values
returned (a numeric connection status indicator, a message sequence
number and a pointer to the message itself, in MacOS pascal-style
string form). We declare variables to receive the returned values, do
the call, check the error and format the return value. <p>
Building the return value is done using <CODE><A
NAME="Py_BuildValue">Py_BuildValue</A></CODE>:
<CODE><PRE>
return Py_BuildValue("iiO&", (int)status, (int)seqnum, PyMac_BuildStr255, message);
</PRE></CODE>
Py_BuildValue() is a very handy routine that builds tuples according
to a format string, somewhat similar to the way <CODE>printf()</CODE>
works. The format string specifies the arguments expected after the
string, and turns them from C objects into python objects. The
resulting objects are put in a python tuple object and returned. The
"i" format specifier signifies an "int" (hence the cast: status and
seqnum are declared as "long", which is what the is_status() routine
wants, and even though we use a 4-byte project there is really no
reason not to put the cast here). Py_BuildValue and its counterpart
Py_ParseTuple have format codes for all the common C types like ints,
shorts, C-strings, floats, etc. Also, there is a nifty escape
mechanism to format values about which is does not know. This is
invoked by the "O&" format: it expects two arguments, a routine
pointer and an int-sized data object. The routine is called with the
object as a parameter and it should return a python objects
representing the data. <CODE>Macglue.h</CODE> declares a number of
such formatting routines for common MacOS objects like Str255, FSSpec,
OSType, Rect, etc. See the comments in the include file for
details. <p>
<CODE>Pyis_getconfig()</CODE> is again similar to pyis_getstatus, only
two minor points are worth noting here. First, the C API return the
input and output baudrate squashed together into a single 4-byte
long. We separate them out before returning the result to
python. Second, whereas the status call returned us a pointer to a
<CODE>Str255</CODE> it kept we are responsible for allocating the
<CODE>Str255</CODE> for getconfig. This is something that would have
been easy to get wrong had we not used prototypes everywhere. Morale:
always try to include the header files for interfaces to libraries and
other stuff, so that the compiler can catch any mistakes you make. <p>
<CODE>Pyis_setconfig()</CODE> finally shows off
<CODE>Py_ParseTuple</CODE>, the companion function to
<CODE>Py_BuildValue</CODE>. You pass it the argument tuple "args"
that your method gets as its second argument, a format string and
pointers to where you want the arguments stored. Again, standard C
types such as strings and integers Py_ParseTuple knows all about and
through the "O&" format you can extend the functionality. For each
"O&" you pass a function pointer and a pointer to a data area. The
function will be called with a PyObject pointer and your data pointer
and it should convert the python object to the correct C type. It
should return 1 on success and 0 on failure. Again, a number of
converters for standard MacOS types are provided, and declared in
<CODE>macglue.h</CODE>. <p>
Next in our source file comes the method table for our module, which
has been generated by modulator (and it did a good job too!), but
which is worth looking at for a moment. Entries are of the form
<CODE><PRE>
{"open", pyis_open, 1, pyis_open__doc__},
</PRE></CODE>
where the entries are python method name, C routine pointer, flags and
docstring pointer. The value to note is the 1 for the flags: this
signifies that you want to use "new-style" Py_ParseTuple behaviour. If
you are writing a new module always use this, but if you are modifying
old code which calls something like <CODE>getargs(args, "(ii)",
...)</CODE> you will have to put zero here. See "extending and
embedding" or possibly the getargs.c source file for details if you
need them. <p>
Finally, we add some code to the init module, to put some symbolic
constants (codes that can by returned by the status method) in the
module dictionary, so the python program can use "interslip.RUN"
instead of the cryptic "4" when it wants to check that the interslip
driver is in RUN state. Modulator has already generated code to get at
the module dictionary using PyModule_GetDict() to store the exception
object, so we simply call
<CODE><PRE>
PyDict_SetItemString(d, "IDLE", PyInt_FromLong(IS_IDLE));
</PRE></CODE>
for each of our items. Since the last bit of code in our init routine
checks for previous errors with <CODE>PyErr_Occurred()</CODE> and
since <CODE>PyDict_SetItemString()</CODE> gracefully handles the case
of <CODE>NULL</CODE> parameters (if <CODE>PyInt_FromLong()</CODE>
failed, for instance) we don't have to do error checking here. In some
other cases you may have to do error checking yourself. <p>
This concludes our crash-course on writing Python extensions in C on
the Macintosh. If you are not done reading yet I suggest you look
back at the <A HREF="index.html">MacPython Crashcourse index</A> to
find another topic to study. <p>

View File

@ -1,93 +0,0 @@
import Printing
from Carbon import Qd
from Carbon import Fm
from Carbon import Res
# some constants
PostScriptBegin = 190 # Set driver state to PostScript
PostScriptEnd = 191 # Restore QuickDraw state
PostScriptHandle = 192 # PostScript data referenced in handle
CHUNK_SIZE = 0x8000 # max size of PicComment
def PostScript(text):
"""embed text as plain PostScript in print job."""
handle = Res.Resource('')
Qd.PicComment(PostScriptBegin, 0, handle)
while text:
chunk = text[:CHUNK_SIZE]
text = text[CHUNK_SIZE:]
handle.data = chunk
Qd.PicComment(PostScriptHandle, len(chunk), handle)
handle.data = ''
Qd.PicComment(PostScriptEnd, 0, handle)
# create a new print record
printrecord = Printing.NewTPrintRecord()
# open the printer
Printing.PrOpen()
try:
# initialize print record with default values
Printing.PrintDefault(printrecord)
# page setup, ok is 0 when user cancelled
ok = Printing.PrStlDialog(printrecord)
if not ok:
raise KeyboardInterrupt
# at this stage, you should save the print record in your document for later
# reference.
# print job dialog, ok is 0 when user cancelled
ok = Printing.PrJobDialog(printrecord)
if not ok:
raise KeyboardInterrupt
# once per document
port = Printing.PrOpenDoc(printrecord)
# port is the Printer's GrafPort, it is also the current port, so no need to Qd.SetPort(port)
try:
# start printing a page
# XXX should really look up what pages to print by
# inspecting the print record.
Printing.PrOpenPage(port, None)
try:
# use QuickDraw like in any other GrafPort
Qd.FrameRect((10, 250, 100, 500))
Qd.FrameRect((10, 510, 100, 600))
Qd.MoveTo(10, 100)
Qd.TextSize(50)
Qd.TextFont(Fm.GetFNum("Helvetica"))
Qd.DrawString("It rreally works!")
Qd.MoveTo(10, 150)
Qd.TextSize(20)
Qd.DrawString("(and now for a little PostScript...)")
# example PostScript code
ps = """
% the coordinate system is the quickdraw one, which is flipped
% compared to the default PS one. That means text will appear
% flipped when used directly from PostScript.
% As an example we start by defining a custom scalefont operator
% that corrects this.
/myscalefont{[exch 0 0 2 index neg 0 0]makefont}def
0.75 setgray
0 0 moveto
0 30 lineto 10000 30 lineto
10000 0 lineto closepath fill
0 setgray
5 25 moveto /Courier findfont 20 myscalefont setfont
(Printed with PostScript!) show
2 setlinewidth [10 10 5 10] 0 setdash 5 5 moveto 400 0 rlineto stroke
"""
# embed the PostScript code in the print job
PostScript(ps)
finally:
# when done with the page
Printing.PrClosePage(port)
finally:
# when done with the document
Printing.PrCloseDoc(port)
finally:
# when done printing
Printing.PrClose()

View File

@ -1,429 +0,0 @@
<HTML>
<HEAD>
<TITLE>Using Python 2.0 on the Macintosh</TITLE>
</HEAD>
<BODY>
<H1>Using Python 2.0 on the Macintosh</H1>
<HR>
This document is an introduction to using Python on the Apple
Macintosh. It does not introduce the language itself, for this you
should refer to the <A
HREF="http://www.python.org/doc/tut/tut.html">Python Tutorial</A> by
Guido van Rossum. This guide more-or-less replaces chapter two of the
tutorial, and provides some additional material. <p>
The tutorial, along with other indispensible documentation like the
library reference and such, is also available in a number of different
formats at <a href="http://www.python.org">
www.python.org</a>. The Adobe Acrobat <code>.pdf</code>
files are probably a good choice for reading or printing the documents
from your mac. <p>
There is currently no good tutorial for the mac-specific features of
Python, but to whet your appetite: it has interfaces to many MacOS
toolboxes (quickdraw, sound, quicktime, open scripting, etc) and
various portable toolboxes are available too (Tk, complex
numbers, image manipulation, etc). Some <A HREF="index.html">
annotated sample programs</A> are available to give you an idea of
Python's power. <P>
<h2>Using Python</h2>
The best way to start using Python is by using the <code>Python IDE</code>,
an integrated development environment with editor, debugger, class browser, etc.
Unfortunately the IDE is not yet documented here. Fortunately, however, it does not
need much documentation, so your best bet is to try it. <p>
<h2>Invoking the bare interpreter</h2>
An alternative method to use Python (and the method this document unfortunately emphasizes,
see the comment above) is to use the bare interpreter and an external text editor.
The name of the interpreter is <CODE>PythonInterpreter</CODE> and it is
recognizable by the "16 ton" icon. You start the
interpreter in interactive mode by double-clicking its icon: <p>
<img src="html.icons/python.gif"><p>
This should give you a text window with an informative version string
and a prompt, something like the following:
<PRE>
Python 1.5.1 (#122 Aug 27, 1997) [CW PPC w/GUSI MSL]
Copyright 1991-1997 Stichting Mathematisch Centrum, Amsterdam
&gt;&gt;&gt;
</PRE>
The version string tells you the version of Python, whether it was
built for PPC or 68K macs and possibly some options used to build the
interpreter. If you find a bug or have a question about how the
interpreter works it is a good idea to include the version information
in your message. <p>
At the prompt you can type interactive python commands. See the
tutorial for more information. The interactive window works
more-or-less like a Communication Toolbox or Telnet window: you type
commands at the bottom and terminate them with the <EM>[return]</EM>
or <EM>[enter]</EM> key. Interpreter feedback also appears at the
bottom of the window, and the contents scroll as output is added. You
can use copy and paste in the normal way, but be sure to paste only at
the bottom of the document.
<h2>Creating Python scripts</h2>
The Python interpreter works in a way that is different from what you
would expect of a macintosh program: the interpreter is just that: an
interpreter. There is no builtin editor or other development
support. Hence, to create a Python script you need an external text
editor. For a first script you can use any editor that can create
plain, unstyled text files, such as <CODE>SimpleText</CODE>. <p>
For more serious scripts, though, it is advisable to use a programmers
editor, such as <CODE>BBEdit</CODE> or <CODE>Alpha</CODE>. BBEdit is
my favorite: it comes in a commercial version but also in a
fully-functional free version <CODE>BBEdit Lite</CODE>. You can
download it from the <A HREF="http://www.barebones.com/">BareBones</A>
site. The free version will probably provide all the functionality
you will ever need. Besides the standard edit facilities it has
multi-file searches and many other goodies that can be very handy when
editing programs. <p>
After you have created your script in the editor of your choice you
drop it on the interpreter. This will start the interpreter executing
the script, again with a console window in which the output appears
and in which you can type input if the script requires it. Normally
the interpreter will close the window and quit as soon as the script
is done executing, see below under <A HREF="#startup">startup
options</A> for a way to change this. <p>
<blockquote>
There is a BBEdit extension available that allows you to run Python
scripts more-or-less straight from your bbedit source window. Check
out the <code>Mac:Tools:BBPy</code> folder.
</blockquote>
It is a good idea to have the names of all your scripts end in
<CODE>.py</CODE>. While this is not necessary for standalone scripts
it is needed for modules, and it is probably a good idea to start the
habit now. <p>
If you do not like to start the Python interpreter afresh for each
edit-run cycle you can use the <CODE>import</CODE> statement and
<CODE>reload()</CODE> function to speed things up in some cases. Here
is Guido's original comment for how to do this, from the 1.1 release
notes: <P>
<BLOCKQUOTE>
Make sure the program is a module file (filename must be a Python
identifier followed by '<CODE>.py</CODE>'). You can then import it
when you test it for the first time. There are now three
possibilities: it contains a syntax error; it gets a runtime error
(unhandled exception); or it runs OK but gives wrong results. (If it
gives correct results, you are done testing and don't need to read the
rest of this paragraph. :-) Note that the following is not
Mac-specific -- it's just that on UNIX it's easier to restart the
entire script so it's rarely useful. <P>
Recovery from a syntax error is easy: edit the file and import it
again. <P>
Recovery from wrong output is almost as easy: edit the file and,
instead of importing it, call the function <CODE>reload()</CODE> with
the module name as argument (e.g., if your module is called
<CODE>foo</CODE>, type <CODE>reload(foo)</CODE>). <P>
Recovery from an exception is trickier. Once the syntax is correct, a
'module' entry is placed in an internal table, and following import
statements will not re-read the file, even if the module's
initialization terminated with an error (one reason why this is done
is so that mutually recursive modules are initialized only once). You
must therefore force re-reading the module with <CODE>reload()</CODE>,
however, if this happens the first time you try to import the module,
the import statement itself has not completed, and your workspace does
not know the module name (even though the internal table of moduesl
does!). The trick is to first import the module again, then reload
it. For instance, <CODE>import foo; reload(foo)</CODE>. Because the
module object already exists internally, the import statement does not
attempt to execute the module again -- it just places it in your
workspace. </BLOCKQUOTE>
<h2>Clickable python scripts</h2>
If you create your script with the correct creator and type, creator
<CODE>'Pyth'</CODE> and type <CODE>'TEXT'</CODE>, you can double-click
your script and it will automatically invoke the interpreter. If you
use BBEdit you can tell it about the Python file type by adding it to
the "file types" sections of the preferences. Then, if you save a file
for the first time you can tell BBEdit to save the file as a Python
script through the "options" choice of the save dialog. <p>
The <CODE>Scripts</CODE> folder contains a script
<CODE>fixfiletypes</CODE> that will recursively traverse a folder and
set the correct creator and type for all files ending in
<CODE>.py</CODE>. <p>
<BLOCKQUOTE>
Older releases of Python used the creator code
<CODE>'PYTH'</CODE> in stead of <CODE>'Pyth'</CODE>. If you still have
older Python sources on your system and named them with
<CODE>'.py'</CODE> extension the <CODE>fixfiletypes</CODE> script will
correct them.
</BLOCKQUOTE>
<h2>Interaction with the user</h2>
Normally, the interpreter will check for user input (mouse clicks,
keyboard input) every once in a while, so it is possible to switch to
other applications while a script runs. It is also possible to
interrupt the interpreter with the standard command-period keypress,
this will raise the <CODE>KeyboardInterrupt</CODE> exception. Scripts
may, however, turn off this behaviour to facilitate their own event
handling. Such scripts can only be killed with the
command-option-escape shortcut.
<h2><A NAME="startup">startup options</A></h2>
If the <EM>option</EM> key is depressed when Python starts executing
the interpreter will bring up an options dialog thru which you can
influence the way the interpreter behaves. Keep the option key
depressed until the dialog comes up. <p>
<img src="html.icons/options.gif"><p>
The options modify the interpreters behaviour in the following way:
<ul>
<li> the interpreter goes to interactive mode (in stead of
exiting) after a script has terminated normally,
<li> for every module imported a line is printed telling you where the
module was loaded from,
<li> do not print the values of expressions executed as statements in
an interactive python (obsolete),
<li> do not buffer stdout and stderr,
<li> print some debugging output during the parsing phase,
<li> keep the output window open when a script terminates.
</ul>
In addition, you can enter a unix-style command line which is passed
to the script in <CODE>sys.argv</CODE>. Sys.argv[0] is always the name
of the script being executed, additional values can be passed
here. Quoting works as expected. <p>
<BLOCKQUOTE>
<EM>Warning:</EM> redirecting standard input or standard output in the
command-line dialog does not work. This is due to circumstances beyond my
control, hence I cannot say when this will be fixed.
</BLOCKQUOTE>
The default options are also settable on a system-wide basis, see the
section on <A HREF="#preferences">editing preferences</A>. <p>
<h2>Module search path</h2>
The module search path, <CODE>sys.path</CODE>, contains the folders
python will search when you import a module. The path is settable on a
system-wide basis (see the preferences section), and normally
comprises the current folder (where the script lives), the
<CODE>Lib</CODE> folder and some of its subfolders and possibly some
more. <p>
<h2>Working folder</h2>
The unix concept of a <I>working directory</I> does not translate
directly to a similar concept on the Macintosh. To facilitate easy
porting and the use of relative pathnames in scripts the interpreter
simulates a working directory. When a script is started the initial
working directory is the folder where the script lives. In case of an
interactive interpreter the working directory is the folder where the
interpreter lives. <P>
By the way: the "standard file" folder, the folder that is presented
to the user initially for an <I>open</I> or <I>save</I> dialog, does
<EM>not</EM> follow the Python working directory. Which folder is
initially shown to the user is usually one of (a) the application
folder, (b) the "Documents" folder or (c) the folder most recently
used for such a dialog (in any Python program). This is standard MacOS
behaviour, so don't blame Python for it. The exact behaviour is
settable through a control panel since System 7.5.
<h2>Interactive startup file</h2>
If the folder containing the interpreter contains a file named
<CODE>PythonStartup</CODE> this file is executed when you start an
interactive interpreter. In this file you could import modules you
often use and other such things. <p>
<h2>Compiled python scripts</h2>
Once a python module has been imported the interpreter creates a
compiled version which is stored in a file with the ".py" extension
replaced by ".pyc". These compiled files, with creator
<CODE>'Pyth'</CODE> and type <CODE>'PYC '</CODE> load faster when
imported (because they do not have to be parsed). The <CODE>Lib</CODE>
folder contains a script <CODE>compileall.py</CODE>, running this
script will cause all modules along the python search path to be
precompiled, which will speed up your programs. Compiled files are
also double-clickable. <p>
<h2>Python resources</h2>
MacPython has the ability to collect a number of compiled modules
together in the resource fork of a single file. This feature is useful
if you distribute a python program and want to minimize clutter: you
can put all the needed modules in a single file (which could even be
the interpreter itself). <p>
If the module search path contains a filename as one of its entries
(as opposed to a folder name, which is the normal case) this file will
be searched for a resource with type <CODE>'PYC '</CODE> and a name
matching the module being imported. <p>
The <CODE>scripts</CODE> folder contains a script
<CODE>PackLibDir</CODE> which will convert a number of modules (or
possibly a complete subtree full of modules) into such a resource
file.
<h2><A NAME="preferences">Setting interpreter preferences</A></h2>
The python interpreter keeps a preferences file in the standard
location in the system folder. In this preferences file it remembers
the default module search path and the default settings for the
runtime options. The preferences are settable via
<CODE>EditPythonPrefs</CODE>. For PPC/cfm68k python this is a standalone
program living in the main Python folder, for 68K python it is a
script in the <CODE>Mac:Scripts</CODE> folder. <p>
The interface to edit the preferences is rather clunky for the current
release. <p>
<img src="html.icons/preferences.gif"><p>
In the editable text field at the top you enter the initial module
search path, using newline as a separator. There are two special
values you can use here: an initial substring <CODE>$(PYTHON)</CODE>
will expand to the Python home folder and a value of
<CODE>$(APPLICATION)</CODE> will expand to the the python application
itself. Note that the text field may extend "beyond the bottom" even
though it does not have a scroll bar. Using the arrow keys works,
though.<p>
The Python home folder $(PYTHON) is initially, when you install Python,
set to the folder where the interpreter lives. You can change it here. <p>
Finally, you can set the default startup options here, through a
sub-dialog.
<h2>Applets</h2>
An applet is a fullblown application written in Python, similar to an
AppleScript applet (and completely different from a Java
applet). Applets are currently supported on PowerPC macintoshes and on
68K macintoshes if you use the CFM68K version of the interpreter,
and are created using the <CODE>BuildApplet</CODE> program. You create an
applet by dropping the python source script onto BuildApplet.
<a href="example2.html">Example 2</a> is a more involved applet
with its own resource file, etc. <p>
Note that while an applet behaves as a fullblown Macintosh application
it is not self-sufficient, so distributing it to a machine without an
installed Python interpreter will not work: it needs the shared python
execution engine <CODE>PythonCore</CODE>, and probably various modules
from the Lib and PlugIns folders. Distributing it to a machine that does
have a Python system will work. <p>
<h2>Customizing applets</h2>
Applets can have their own settings for the startup options and module
search path. Dropping an applet on the <CODE>EditPythonPrefs</CODE>
application allows you to set these, in the same way as
double-clicking EditPythonPrefs allows you to set the system-wide
defaults. <p>
Actually, not only applets but also the interpreter itself can have
non-default settings for path and options. If you make a copy of the
interpreter and drop this copy onto EditPythonPrefs you will have an
interpreter that has a different set of default settings. <p>
<h2>Where to go from here</h2>
The previously mentioned <A
HREF="http://www.python.org/doc/tut/tut.html">Python Tutorial</A> is
an excellent place to start reading if you have never used Python
before. Other documentation such as the library reference manual is
indexed at the <A HREF="http://www.python.org/doc/">Python
Documentation</A> page. <p>
There are some <A HREF="index.html">annotated sample programs</A>
available that show some mac-specific issues, like use of various
toolboxes and creation of Python applets. <p>
The <CODE>Demo</CODE> and <CODE>Mac:Demo</CODE>
folders in the Macintosh distribution
contains a number of other example programs. Most of these are only
very lightly documented, but they may help you to understand some
aspects of using Python. <p>
Finally, there is a <code>Mac:Contrib</code> folder that contains
a few contributions to Python that I couldn't fit in the normal tree
but did want to distribute (many other contributions are contained
throughout the distribution, but you don't see them, really).
The best way to contact fellow Macintosh Python programmers is to join
the MacPython Special Interest Group mailing list. Send a message with
"info" in the body to <A
HREF="mailto:pythonmac-sig-request@python.org">pythonmac-sig-request@python.org</A>
or view the <A
HREF="http://www.python.org/sigs/pythonmac-sig/">Pythonmac SIG
page</A> on the <A HREF="http://www.python.org">www.python.org</A> WWW
server. <p>
<h2>Troubleshooting</h2>
A rather baffling error message can be "PythonCore not found" when you
start the interpreter and you are sure that PythonCore is available. The
message should actually say "Not enough memory in the system heap to
load PythonCore".
Blame Apple for the confusing message. <p>
There appear to be problems with QuickTime for the CFM68K version of the
interpreter. If you experience these please contact the SIG: some people
use quicktime without problems and some not, and we are still hunting for
the cause. <p>
Python is a rather safe language, and hence it should be difficult to
crash the interpreter of the system with a Python script. There is an
exception to this rule, though: the modules that interface to the
system toolboxes (windowing, quickdraw, etc) do very little error
checking and therefore a misbehaving program using these modules may
indeed crash the system. Such programs are unfortunately rather
difficult to debug, since the crash does not generate the standard
Python stack trace, obviously, and since debugging print statements
will often interfere with the operation of the program. There is
little to do about this currently. <p>
Probably the most common cause of problems with modules ported from
other systems is the Mac end-of-line convention. Where unix uses
linefeed, 0x0a, to separate lines the mac uses carriage return,
0x0d. To complicate matters more a lot of mac programming editors like
BBEdit and emacs will work happily with both conventions, so the file
will appear to be correct in the editor but cause strange errors when
imported. BBEdit has a popup menu which allows you to inspect (and
set) the end-of-line convention used in a file. <p>
Python attempts to keep its preferences file up-to-date even when you
move the Python folder around, etc. If this fails the effect will be
that Python cannot start or, worse, that it does work but it cannot find
any standard modules. In this case, start Python and examine <code>sys.path</code>.
If it is incorrect remove any Python preferences file from the system
folder and start the interpreter <em>while the interpreter sits in the main
Python folder</em>. This will regenerate the preferences file. You may also
have to run the ConfigurePython applet again. <p>
<h2>Your five minutes are up. Next!</h2>
The next section to check out is the <a href="index.html">annotated sample programs</a>.<p>
<HR>
<A HREF="http://www.cwi.nl/~jack">Jack Jansen</A>,
<A HREF="mailto:jack@cwi.nl">jack@cwi.nl</A>, 10-Sep-00.
</BODY>
</HTML>