Commits

Anonymous committed 22f5302

Changes to packaging and templates; 0.8 release candidate.

Comments (0)

Files changed (12)

+2002-12-17  Bill Bumgarner  <bbum@codefab.com>
+
+    * Project Templates/Cocoa-Python Application/MyAppDelegate.py: Moved to
+    AutoBaseClass.  Added significant documentation.
+
+    * Project Templates/Cocoa-Python Application/bin-python-main.m: Integrated
+    all of Jack's, Ronald's and my suggestions/patches/changes (that I could
+    remember).
+
+    * Project Templates/Cocoa-Python Application/__main__.py: Brought in line
+    with Web Services Tool example.  Minimized the # of lines.
+
+    * setup.py: Added test directories.
+
+    * MANIFEST: Completely redid.
+
+    * Scripts/buildpkg.py (PackageMaker.build): Tried to add RootOnly install
+    flag.  Won't work until we move to new style packaging format.
+
+    * ReadMe.txt: Added brief note about installing the packaged version.
+
+    * Scripts/make_distrib.py (fd): Numerous changes.  Final products are
+    built into a directory that can be directly disk imaged.  Directory
+    contains readme, license, and changelog.  Package now contains developer
+    examples. More cleanup of spurious files from trees to be packaged.
+
+    * Cleaned up Cocoa-Python template;  synchronized with WebServicesTool
+      example.  Added lots of comments.
+
 2002-12-15 Ronald Oussoren <oussoren@cistron.nl>
     * Erase reference to the Python half before doing the [super release] 
       call that will release the Objective-C half of an instance of a
Add a comment to this file

pyobjc/Installer Package/PyObjC.pmsp

Binary file removed.

 ./BUGS
 ./ChangeLog
 ./Doc/architecture.txt
+./Doc/classes.txt
 ./Doc/structure.txt
 ./Doc/TODO
 ./Doc/users.txt
 ./Doc/warts.txt
+./Doc/wrapping.txt
 ./Examples/00ReadMe.txt
 ./Examples/addressbook.py
+./Examples/CurrencyConverter/buildapp.py
 ./Examples/CurrencyConverter/CurrencyConverter.py
 ./Examples/CurrencyConverter/English.lproj/InfoPlist.strings
 ./Examples/CurrencyConverter/English.lproj/MainMenu.nib/classes.nib
 ./Examples/CurrencyConverter/English.lproj/MainMenu.nib/info.nib
 ./Examples/CurrencyConverter/English.lproj/MainMenu.nib/objects.nib
-./Examples/CurrencyConverter/setup-app.py
 ./Examples/dictionary.py
 ./Examples/HelloWorld.py
 ./Examples/iClass/datasource.py
 ./Examples/iClass/English.lproj/MainMenu.nib/info.nib
 ./Examples/iClass/English.lproj/MainMenu.nib/objects.nib
 ./Examples/iClass/main.py
-./Examples/iClass/setup-app.py
 ./Examples/method-weirdness.py
 ./Examples/objc-vars.py
 ./Examples/pydict-to-objcdict.py
 ./Examples/subclassing-objective-c.py
 ./Examples/super-call.py
 ./Examples/TableModel/00ReadMe.txt
+./Examples/TableModel/buildapp.py
 ./Examples/TableModel/English.lproj/MainMenu.nib/classes.nib
 ./Examples/TableModel/English.lproj/MainMenu.nib/info.nib
 ./Examples/TableModel/English.lproj/MainMenu.nib/objects.nib
-./Examples/TableModel/setup-app.py
 ./Examples/TableModel/TableModel.py
 ./Examples/TableModel2/English.lproj/InfoPlist.strings
 ./Examples/TableModel2/English.lproj/MainMenu.nib/classes.nib
 ./Examples/TableModel2/main.m
 ./Examples/TableModel2/README.txt
 ./Examples/TableModel2/TableModel.py
+./Examples/TableModel2/TableModel2.pbproj/bbum.pbxuser
 ./Examples/TableModel2/TableModel2.pbproj/project.pbxproj
 ./Examples/Todo/00ReadMe.txt
-./Examples/Todo/buildpyapp.sh
+./Examples/Todo/buildapp.py
 ./Examples/Todo/CalendarMatrix.py
 ./Examples/Todo/English.lproj/Credits.rtf
 ./Examples/Todo/English.lproj/InfoPlist.strings
 ./Examples/Todo/InfoWindowController.py
 ./Examples/Todo/main.py
 ./Examples/Todo/SelectionNotifyMatrix.py
-./Examples/Todo/setup-app.py
 ./Examples/Todo/TodoAppDelegate.py
 ./Examples/Todo/ToDoCell.py
 ./Examples/Todo/ToDoDocument.py
 ./Examples/Todo/ToDoItem.py
 ./Examples/using-nscoder.py
 ./Examples/using-nsscanner.py
+./Examples/WebServicesTool/__main__.py
+./Examples/WebServicesTool/bin-python-main.m
 ./Examples/WebServicesTool/English.lproj/InfoPlist.strings
 ./Examples/WebServicesTool/English.lproj/MainMenu.nib/classes.nib
 ./Examples/WebServicesTool/English.lproj/MainMenu.nib/info.nib
 ./Examples/WebServicesTool/English.lproj/MainMenu.nib/keyedobjects.nib
+./Examples/WebServicesTool/English.lproj/MainMenu~.nib/classes.nib
+./Examples/WebServicesTool/English.lproj/MainMenu~.nib/info.nib
+./Examples/WebServicesTool/English.lproj/MainMenu~.nib/keyedobjects.nib
 ./Examples/WebServicesTool/English.lproj/WSTConnection.nib/classes.nib
 ./Examples/WebServicesTool/English.lproj/WSTConnection.nib/info.nib
 ./Examples/WebServicesTool/English.lproj/WSTConnection.nib/keyedobjects.nib
 ./Examples/WebServicesTool/LICENSE.txt
-./Examples/WebServicesTool/main-bin-python.m
-./Examples/WebServicesTool/main-embedded-interpreter.m
-./Examples/WebServicesTool/Main.py
 ./Examples/WebServicesTool/Preferences.png
 ./Examples/WebServicesTool/README.txt
 ./Examples/WebServicesTool/Reload.png
 ./Examples/WebServicesTool/WSTConnectionWindowControllerClass.py
 ./FIXME
 ./INSTALL
-./Installer Package/PyObjC.pmsp
 ./Installer Package/Resources/Description.plist
 ./Installer Package/Resources/License.txt
 ./Installer Package/Resources/ReadMe.txt
 ./Lib/AppKit/__init__.py
 ./Lib/AppKit/_AppKitSignatures.py
 ./Lib/AppKit/AppKit.byref
+./Lib/AppKit/NibClassBuilder.py
 ./Lib/Foundation/__init__.py
 ./Lib/Foundation/Foundation.byref
+./Lib/Foundation/test/test_nsarray.py
+./Lib/Foundation/test/test_nsautoreleasepool.py
+./Lib/Foundation/test/test_nsdictionary.py
+./Lib/Foundation/test/test_nsexception.py
+./Lib/Foundation/test/test_nsnumber.py
+./Lib/Foundation/test/test_nsobject.py
+./Lib/Foundation/test/test_nsset.py
+./Lib/Foundation/test/test_paths.py
 ./Lib/Foundation/test/test_subclassing.py
-./Lib/Foundation/test/test_nsobject.py
 ./Lib/objc/__init__.py
 ./Lib/objc/_convenience.py
 ./Lib/objc/_FoundationSignatures.py
-./Lib/objc/builder.py
-./Lib/objc/classnib.py
 ./Lib/objc/test/test_objc.py
+./Lib/objc/test/test_subclass.py
 ./License.txt
-./MANIFEST
 ./Modules/Cocoa/00ReadMe.txt
 ./Modules/Cocoa/_App_Enum.inc
 ./Modules/Cocoa/_App_Functions.inc
 ./Modules/Cocoa/Foundation.prototypes
 ./Modules/Cocoa/func_builder.err
 ./Modules/Cocoa/func_builder.out
+./Modules/Cocoa/NSAutoreleasePoolSupport.m
 ./Modules/Cocoa/scripts/cocoa_generator.py
 ./Modules/Cocoa/scripts/enum_generator.py
 ./Modules/Cocoa/scripts/func_builder.py
 ./Modules/Cocoa/scripts/func_collector.py
 ./Modules/Cocoa/scripts/strconst_generator.py
 ./Modules/Cocoa/scripts/var_generator.py
+./Modules/objc/alloc_hack.m
 ./Modules/objc/class-builder.h
 ./Modules/objc/class-builder.m
 ./Modules/objc/class-list.m
 ./Modules/objc/signatures.lst
 ./Modules/objc/super-call.h
 ./Modules/objc/super-call.m
+./MPCompat/bundlebuilder.py
+./MPCompat/plistlib.py
+./MPCompat/README
 ./NEWS
 ./Project Templates/00README.txt
+./Project Templates/Cocoa-Python Application/__main__.py
 ./Project Templates/Cocoa-Python Application/bin-python-main.m
 ./Project Templates/Cocoa-Python Application/CocoaApp.pbproj/project.pbxproj
 ./Project Templates/Cocoa-Python Application/CocoaApp.pbproj/TemplateInfo.plist
 ./Project Templates/Cocoa-Python Application/English.lproj/MainMenu.nib/classes.nib
 ./Project Templates/Cocoa-Python Application/English.lproj/MainMenu.nib/info.nib
 ./Project Templates/Cocoa-Python Application/English.lproj/MainMenu.nib/keyedobjects.nib
-./Project Templates/Cocoa-Python Application/Main.py
 ./Project Templates/Cocoa-Python Application/MyAppDelegate.py
-./Project Templates/install.sh
 ./README-OLD.txt
 ./ReadMe.txt
+./Scripts/buildpkg.py
+./Scripts/create_byref_module.py
 ./Scripts/extract_byref_signatures.py
 ./Scripts/generate-stubs.py
+./Scripts/make_distrib.py
+./Scripts/nibclassbuilder
 ./Scripts/README
 ./setup.py
-./Tools/README

pyobjc/Project Templates/Cocoa-Python Application/CocoaApp.pbproj/project.pbxproj

 				4A9504CCFFE6A4B311CA0CBA,
 				4A9504CDFFE6A4B311CA0CBA,
 			);
+			hasScannedForEncodings = 1;
 			isa = PBXProject;
 			mainGroup = 29B97314FDCFA39411CA2CEA;
 			projectDirPath = "";
 </dict>
 </plist>
 ";
-			shouldUseHeadermap = 1;
 		};
 		29B97327FDCFA39411CA2CEA = {
 			buildActionMask = 2147483647;
 //F63
 //F64
 		F60DD8BC0358A22201C8ED3C = {
+			fileEncoding = 30;
 			isa = PBXExecutableFileReference;
 			path = __main__.py;
 			refType = 2;
 		};
 		F60DD8BD0358A22201C8ED3C = {
+			fileEncoding = 30;
 			isa = PBXFileReference;
 			path = MyAppDelegate.py;
 			refType = 2;

pyobjc/Project Templates/Cocoa-Python Application/MyAppDelegate.py

 #  Copyright (c) �YEAR� �ORGANIZATIONNAME�. All rights reserved.
 #
 
-from objc import IBOutlet
+# import needed classes/functions from Foundation
 from Foundation import NSObject, NSProcessInfo, NSFullUserName, NSLog
 
-class MyAppDelegate (NSObject):
-  messageTextField = IBOutlet("messageTextField")
-  
-  def sayHelloAction_(self, sender):
-    userName = NSFullUserName()
-    hostName = NSProcessInfo.processInfo().hostName()
-    helloString = "Hello %s @ %s!" % (userName, hostName)
+# import Nib loading functionality from AppKit
+from AppKit import NibClassBuilder
+from AppKit.NibClassBuilder import AutoBaseClass
+
+# create ObjC classes as defined in MainMenu.nib
+NibClassBuilder.extractClasses("MainMenu")
+class MyAppDelegate(AutoBaseClass):
+    """
+    The application's delegate.
+
+    An instance of this class is instantiated in the MainMenu.nib file
+    to act as the Application's delegate and as the target of the
+    sayHello: action.
+
+    Note that by inheriting from AutoBaseClass, PyObjC will
+    automatically define MyAppDelegate based on the definition of
+    MyAppDelegate in MainMenu.nib.  The inheritance of this class will
+    be determined by the class definition in the NIB and all outlets
+    will automatically be defined.
+
+    Action methods are not automatically defined as this follows the
+    ObjC behavior;  the AppKit automatically prints a warning upon NIB
+    loading if a target/action connection could not be made.
+    """
+    def sayHelloAction_(self, sender):
+        """
+        An example of a standard target action method implementation.
+        """
+        userName = NSFullUserName()
+        hostName = NSProcessInfo.processInfo().hostName()
+        helloString = "Hello %s @ %s!" % (userName, hostName)
     
-    self.messageTextField.setStringValue_( helloString )
-    NSLog( "Saying: %s" % helloString )
+        self.messageTextField.setStringValue_(helloString)
+        NSLog( "Saying: %s" % helloString )
     
-  def applicationDidFinishLaunching_(self, aNotification):
-    NSLog( "Application did finish launching." )
+    def applicationDidFinishLaunching_(self, aNotification):
+        """
+        Invoked by NSApplication once the app is done launching and
+        immediately before the first pass through the main event
+        loop.
+        """
+        NSLog( "Application did finish launching." )
+        self.messageTextField.setStringValue_("Click the button.")

pyobjc/Project Templates/Cocoa-Python Application/__main__.py

 #  Copyright (c) �YEAR� �ORGANIZATIONNAME�. All rights reserved.
 #
 
-# 
-# Upon an installation build, the project copies the PyObjC modules
-# into the 'pyobjc' directory within the Resources directory of
-# the app wrapper.  The following adjusts sys.path to include that
-# directory.
-#
-import sys
-import os.path
-sys.path.insert(0, os.path.join(sys.path[0], "pyobjc"))
-
-#
-# Import the components of the Python<->ObjC bridge.
-#
+# import PyObjC
 import objc
 import Foundation
 import AppKit
 
-#
-# Automatically load any frameworks identified by the bootstrap
-# process (the code in bin-python-main.m).
-#
-# If any of the frameworks have an Init.py, it will be executed
-# and, as such, can be used to load/initialize any of the
-# frameworks in the Python interpreter context.
-#
-pyFrameworkPathsIndex = sys.argv.index("-PyFrameworkPaths")
-if not (pyFrameworkPathsIndex == -1):
-  import string
-  from Foundation import NSBundle
-  paths = string.split(sys.argv[pyFrameworkPathsIndex + 1], ":")
-  count = 0
-  for path in paths:
-    bundle = NSBundle.bundleWithPath_(path)
-    bundle.principalClass()
-    sys.path.insert(count, bundle.resourcePath())
-    count = count + 1
-    
-    initPath = bundle.pathForResource_ofType_( "Init", "py")
-    if initPath:
-      execfile(initPath, globals(), locals())
-
-#
-# Import application specific componentry.  At the least, all
-# classes necessary to load the main NIB file must be loaded here.
-#
+# import classes required to start application
 import MyAppDelegate
 
-#
-# Pass control to the Appkit.
-#
-# From this point on, application intiailization, execution and
-# termination works exactly like any other Cocoa application.
-#
-sys.exit( AppKit.NSApplicationMain(sys.argv) )
+# pass control to the AppKit
+import sys
+sys.exit(AppKit.NSApplicationMain(sys.argv))

pyobjc/Project Templates/Cocoa-Python Application/bin-python-main.m

 /*
  This main file uses execve() to transfer control of execution to the standard command line python interpreter.   As such, compiled classes in the project will not actually be linked into the runtime as execve() effectively overlays the existing process with the process being called -- in this case the python command line tool.
 
- To use compiled classes with this main, create a separate bundle target and load the bundle in the Main.py file.
+ To use compiled classes with this main, create a separate bundle target and load the bundle in the main python file.  The main python file should be in Resources and should be named "__main__.py", "__realmain__.py" or "Main.py".
 
  This style of execution works with the Apple provided version of Python.
  */
 
 int pyobjc_main(int argc, char * const *argv, char * const *envp)
 {
-  // The autorelease pool is not released on purpose.   The call to execve() destroys the
-  // calling process entirely and, as such, memory management in the traditional sense
-  // is not necessary (and not doing so avoids potential bugs associated with releasing
-  // the pool prior to the call to execve).
-  [[NSAutoreleasePool alloc] init];
+    // The autorelease pool is not released on purpose.   The call to execve() destroys the
+    // calling process entirely and, as such, memory management in the traditional sense
+    // is not necessary (and not doing so avoids potential bugs associated with releasing
+    // the pool prior to the call to execve).
+    [[NSAutoreleasePool alloc] init];
 
-  const char **childArgv = alloca(sizeof(char *) * (argc + 5));
-  NSEnumerator *bundleEnumerator = [[NSBundle allFrameworks] reverseObjectEnumerator];
-  NSBundle *aBundle;
-  NSBundle *mainBundle = [NSBundle mainBundle];
-  NSMutableArray *bundlePaths = [NSMutableArray array];
-  int i;
-  char** childEnvp;
-  char*  PYTHONPATH = NULL;
+    const char **childArgv = alloca(sizeof(char *) * (argc + 5));
+    NSEnumerator *bundleEnumerator = [[NSBundle allFrameworks] reverseObjectEnumerator];
+    NSBundle *aBundle;
+    NSBundle *mainBundle = [NSBundle mainBundle];
+    NSMutableArray *bundlePaths = [NSMutableArray array];
+    int i;
+    int envc;
+    char** childEnvp;
+    char*  PYTHONPATH = NULL;
 
-  // count entries in environment and find the PYTHONPATH setting, if present
-  for (envc = 0; envp[envc] != NULL; envc++) {
-    if (strncmp(envp[envc], "PYTHONPATH=", sizeof("PYTHONPATH=")-1) == 0) {
-      PYTHONPATH=envp[envc] + sizeof("PYTHONPATH=") - 1;
-      /* No break, we also want to know how large envp is */
+    // set up paths to be prepended to the PYTHONPATH
+    const char *pythonPathInWrapper = [[NSString stringWithFormat: @"%@:%@",
+        [[NSBundle mainBundle] resourcePath],
+        [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent: @"pyobjc"]] UTF8String];
+
+    // count entries in environment and find the PYTHONPATH setting, if present
+    for (envc = 0; envp[envc] != NULL; envc++) {
+        if (strncmp(envp[envc], "PYTHONPATH=", sizeof("PYTHONPATH=")-1) == 0) {
+            PYTHONPATH=envp[envc] + sizeof("PYTHONPATH=") - 1;
+            /* No break, we also want to know how large envp is */
+        }
     }
-  }
 
-  childEnvp = alloca(sizeof(char*) * (envc + 10)); // enough for both PYTHONPATH and the DYLD stuff
-  for (envc = 0; envp[envc] != NULL; envc ++) {
-    if (strncmp(envp[envc], "PYTHONPATH=", sizeof("PYTHONPATH=")-1) == 0) {
-      const char* s = [[[NSBundle mainBundle] resourcePath] UTF8String];
-      childEnvp[envc] = alloca(strlen(envp[envc]) + strlen(s) + 2);
-      sprintf(childEnvp[envc], "%s:%s", s, envp[envc]);
+    // copy the environment into a new array that will eventually also contain the PYTHONPATH
+    childEnvp = alloca(sizeof(char*) * (envc + 10)); // enough for both PYTHONPATH and the DYLD stuff
+    for (envc = 0; envp[envc] != NULL; envc ++) {
+        if (strncmp(envp[envc], "PYTHONPATH=", sizeof("PYTHONPATH=")-1) == 0) {
+            // already exisxts, prepend app wrapper paths
+            NSString *envValue = [NSString stringWithFormat: @"PYTHONPATH=%s:%s", pythonPathInWrapper, PYTHONPATH];
+            childEnvp[envc] = (char *)[envValue UTF8String];
+        } else {
+            childEnvp[envc] = envp[envc];
+        }
+    }
+    if (PYTHONPATH) {
+        // already set in for() loop above
+        childEnvp[envc] = NULL;
     } else {
-      childEnvp[envc] = envp[i];
+        // wasn't set -- add PYTHONPATH to child
+        NSString *envValue = [NSString stringWithFormat: @"PYTHONPATH=%s", pythonPathInWrapper];
+        childEnvp[envc] = (char *)[envValue UTF8String];
+        envc++;
+        childEnvp[envc] = NULL;
     }
-  }
-  if (PYTHONPATH) {
-    envp[envc] = NULL;
-  } else {
-    const char* s = [[[NSBundle mainBundle] resourcePath] UTF8String];
-    childEnvp[envc] = alloca(sizeof("PYTHONPATH=") + strlen(s));
-    sprintf(childEnvp[envc], "PYTHONPATH=%s", s);
-    childEnvp[envc+1] = NULL;
-  }
 
-  // if this is set, it is most likely because of PBX or because the developer is doing something....
-  if ( !getenv("DYLD_FRAMEWORK_PATH") ) {
-    // if not, put the DYLD environment into a state where we can actually load frameworks from within the app
-    // wrapper where the frameworks may have inter-dependencies.
-    NSArray *paths = [NSArray arrayWithObjects: [mainBundle sharedFrameworksPath], [mainBundle privateFrameworksPath], nil];
-    NSString *joinedPaths = [paths componentsJoinedByString: @":"];
-    const char *dyldFrameworkPath = [[NSString stringWithFormat: @"DYLD_FRAMEWORK_PATH=%@", joinedPaths] UTF8String];
-    const char *dyldLibraryPath = [[NSString stringWithFormat: @"DYLD_LIBRARY_PATH=%@", joinedPaths] UTF8String];
+    // if this is set, it is most likely because of PBX or because the developer is doing something....
+    if ( !getenv("DYLD_FRAMEWORK_PATH") ) {
+        // if not, put the DYLD environment into a state where we can actually load frameworks from within the app
+        // wrapper where the frameworks may have inter-dependencies.
+        NSArray *paths = [NSArray arrayWithObjects: [mainBundle sharedFrameworksPath], [mainBundle privateFrameworksPath], nil];
+        NSString *joinedPaths = [paths componentsJoinedByString: @":"];
+        const char *dyldFrameworkPath = [[NSString stringWithFormat: @"DYLD_FRAMEWORK_PATH=%@", joinedPaths] UTF8String];
+        const char *dyldLibraryPath = [[NSString stringWithFormat: @"DYLD_LIBRARY_PATH=%@", joinedPaths] UTF8String];
 
-    childEnvp[i++] = (char *)dyldFrameworkPath;
-    childEnvp[i++] = (char *)dyldLibraryPath;
+        childEnvp[envc++] = (char *)dyldFrameworkPath;
+        childEnvp[envc++] = (char *)dyldLibraryPath;
 
-    // useful for debugging-- set this as a default.
-    if ([[NSUserDefaults standardUserDefaults] boolForKey: @"DYLD_PRINT_LIBRARIES"])
-      childEnvp[i++] = (char *)"DYLD_PRINT_LIBRARIES=1";
-    childEnvp[i++] = NULL;
-  }
+        // useful for debugging-- set this as a default.
+        if ([[NSUserDefaults standardUserDefaults] boolForKey: @"DYLD_PRINT_LIBRARIES"])
+            childEnvp[envc++] = (char *)"DYLD_PRINT_LIBRARIES=1";
+        childEnvp[envc++] = NULL;
+    }
 
-  // grab a list of all frameworks that were linked into this executable
-  while ( aBundle = [bundleEnumerator nextObject] ) {
-    if ( [[[aBundle bundlePath] pathExtension] isEqualToString: @"framework"] )
-      [bundlePaths addObject: [aBundle bundlePath]];
-  }
+    // grab a list of all frameworks that were linked into this executable
+    while ( aBundle = [bundleEnumerator nextObject] ) {
+        if ( [[[aBundle bundlePath] pathExtension] isEqualToString: @"framework"] )
+            [bundlePaths addObject: [aBundle bundlePath]];
+    }
 
-  // figure out which python interpreter to use
-  NSString *pythonBinPath = [[NSUserDefaults standardUserDefaults] stringForKey: @"PythonBinPath"];
-  pythonBinPath = pythonBinPath ? pythonBinPath : @"/usr/bin/python";
+    // set an environment variable to contain the linked frameworks
+    childEnvp[envc++] = (char*)[[NSString stringWithFormat: @"PYOBJCFRAMEWORKS=%@", [bundlePaths componentsJoinedByString: @":"]] UTF8String];
+    childEnvp[envc++] = NULL;
 
-  const char *pythonBinPathPtr = [pythonBinPath UTF8String];
+    // figure out which python interpreter to use
+    NSString *pythonBinPath = [[NSUserDefaults standardUserDefaults] stringForKey: @"PythonBinPath"];
+    pythonBinPath = pythonBinPath ? pythonBinPath : @"/usr/bin/python";
 
-  // find main python file.  __main__.py seems to be a standard.
-  NSString *mainPyPath = [mainBundle pathForResource: @"__main__.py" ofType: nil];
-  if ( !mainPyPath )
-    [NSException raise: NSInternalInconsistencyException
-                format: @"%s:%d pyobjc_main() Failed to find file __main__.py in app wrapper.  Exiting.", __FILE__, __LINE__];
-  const char *mainPyPathPtr = [mainPyPath UTF8String];
+    const char *pythonBinPathPtr = [pythonBinPath UTF8String];
 
-  // construct argv for the child
+    // find main python file.  __main__.py seems to be a standard.
+    NSArray *possibleMains = [NSArray arrayWithObjects:
+        @"__main__.py",
+        @"__main__.pyc",
+        @"__main__.pyo",
+        @"__realmain__.py",
+        @"__realmain__.pyc",
+        @"__realmain__.pyo",
+        @"Main.py",
+        @"Main.pyc",
+        @"Main.pyo",
+        nil];
+    NSEnumerator *possibleMainsEnumerator = [possibleMains objectEnumerator];
+    NSString *mainPyPath;
+    NSString *nextFileName;
 
-  // the path to the executable in the app wrapper -- must be in the app wrapper or CFBundle does not initialize correctly
-  childArgv[0] = argv[0];
+    while (nextFileName = [possibleMainsEnumerator nextObject]) {
+        mainPyPath = [mainBundle pathForResource: nextFileName ofType: nil];
+        if ( mainPyPath )
+            break;
+    }
 
-  // path to the python file that acts as the main entry point
-  childArgv[1] = mainPyPathPtr;
+    if ( !mainPyPath )
+        [NSException raise: NSInternalInconsistencyException
+                    format: @"%s:%d pyobjc_main() Failed to find one of %@ in app wrapper.  Exiting.", __FILE__, __LINE__, possibleMains];
+    const char *mainPyPathPtr = [mainPyPath UTF8String];
 
-  // Pass original arguments (such as -NSOpen) verbatum
-  //
-  // Move each argument right one slot
-  for (i = 1; i<argc; i++)
-    childArgv[i+1] = argv[i];
-  i++; // compensate for i+1 in for() loop
+    // construct argv for the child
 
-  // add an argument that lists all frameworks
-  childArgv[i++] = "-PyFrameworkPaths";
-  childArgv[i++] = [[bundlePaths componentsJoinedByString: @":"] UTF8String];
+    // the path to the executable in the app wrapper -- must be in the app wrapper or CFBundle does not initialize correctly
+    childArgv[0] = argv[0];
 
-  // terminate the arg list
-  childArgv[i++] = NULL;
+    // path to the python file that acts as the main entry point
+    childArgv[1] = mainPyPathPtr;
 
-  // print a nice debugging helper message, if desired
-  if ([[[NSProcessInfo processInfo] environment] objectForKey: @"SHOWPID"])
-    NSLog(@"Process ID is: %d (\n\tgdb %s %d\n to debug)", getpid(), pythonBinPathPtr, getpid());
+    // Pass original arguments (such as -NSOpen) verbatum
+    //
+    // Move each argument right one slot
+    for (i = 1; i<argc; i++)
+        childArgv[i+1] = argv[i];
+    i++; // compensate for i+1 in for() loop
 
-  // pass control to the python interpreter
-  return execve(pythonBinPathPtr, (char **)childArgv, childEnvp);
+    // terminate the arg list
+    childArgv[i++] = NULL;
+
+    // print a nice debugging helper message, if desired
+    if ([[[NSProcessInfo processInfo] environment] objectForKey: @"SHOWPID"])
+        NSLog(@"Process ID is: %d (\n\tgdb %s %d\n to debug)", getpid(), pythonBinPathPtr, getpid());
+
+    // pass control to the python interpreter
+    if (execve(pythonBinPathPtr, (char **)childArgv, childEnvp) == -1)
+        perror("execve");
+    return 1;
 }
 
 int main(int argc, char * const *argv, char * const *envp)
 {
-  return pyobjc_main(argc, argv, envp);
+    return pyobjc_main(argc, argv, envp);
 }

pyobjc/Project Templates/install.sh

-#!/bin/sh
-
-TARGET=$1/Developer/ProjectBuilder\ Extras/Project\ Templates/Application
-
-mkdir -p "$TARGET"
-
-gnutar -c -f - -v -p --exclude=CVS Cocoa-Python\ Application | \
-    ( cd "$TARGET" ; gnutar xfvp - )

pyobjc/ReadMe.txt

+If you are reading this from the PyObjC disk image that contains the Installer
+package, simply Install the package and look in /Developer/Examples/PyObjC.
+Documentation is completely lacking at this point.  Sorry-- it is next on the
+list of things to add to the module.
+
 The PyObjC package provides the glue needed to interface the Python interpreter with the Objective-C language. The 'objc' module makes Objective-C objects and classes available as first-class Python citizens, it is not only possible to use Objective-C objects but you can also subclass Objective-C classes.
 
 If you are installing from the Installer package, it also installs a Project Builder template for building Python based Cocoa applications.  Once installed, create a new "Cocoa-Python Application" project in Project Builder.  The newly created project includes an application delegate implementation and a simple set of Cocoa controls-- i.e. it provides a complete example of how to build a Cocoa application using Python and the PyObjC bridge.

pyobjc/Scripts/buildpkg.py

         'Required': 'NO',
         'InstallOnly': 'NO',
         'RequiresReboot': 'NO',
-        'InstallFat': 'NO'}
+        'InstallFat': 'NO',
+        'RootVolumeOnly' : 'NO'}
 
 
     def __init__(self, title, version, desc):

pyobjc/Scripts/make_distrib.py

 import sys
 import getopt
 import os
+import errno
 import buildpkg
 import shutil
 
 	sys.argv[0], sys.executable)
 
 PYTHON=sys.executable
-OUTPUTDIR='release-dir'
 
 def package_version():
 	fp = open('Modules/objc/pyobjc.h', 'r')  
 	for ln in fp.readlines():
 		if ln.startswith('#define OBJC_VERSION'):
 			fp.close()
+                        break
 	return ln.split()[-1][1:-1]
 
 	raise ValueError, "Version not found"
 
+packageVersion = package_version()
+if (len(packageVersion) < 3) or (len(packageVersion) > 7):
+        raise ValueError, "Version 'found' (%s), but seems preposterously short or long." % packageVersion
+
+BUILDDIR='release-dir'
+OUTPUTDIR='release-dir/PyObjC-%s' % package_version()
 
 def escquotes(val):
 	return val.replace("'", "'\"'\"'")
 	else:
 		raise ValueError, "Unsupported option: %s=%s"%(key, value)
 
+def makeDir(basedir, *path):
+        base = basedir
+        for p in path:
+                base = os.path.join(base, p)
+                try:
+                        os.mkdir(base)
+                except OSError, e:
+                        if e.errno <> errno.EEXIST: raise
+
+
+if not os.path.exists(BUILDDIR):
+        apply(makeDir, ["."] + BUILDDIR.split(os.sep))
+
 if not os.path.exists(OUTPUTDIR):
-	try:
-		os.mkdir(OUTPUTDIR)
-	except os.error, msg:
-		sys.stderr.write("%s: Cannot create %s: %s\n"%(
-			sys.argv[0], OUTPUTDIR, msg))
-		sys.exit(1)
+        apply(makeDir, ["."] + OUTPUTDIR.split(os.sep))
 
 
 if PYTHON==sys.executable:
 	sys.stdout.write(ln)
 
 print "Running: '%s' setup.py install --prefix='%s/package%s'"%(
-	escquotes(PYTHON), escquotes(OUTPUTDIR), escquotes(basedir))
+	escquotes(PYTHON), escquotes(BUILDDIR), escquotes(basedir))
 fd = os.popen("'%s' setup.py install --prefix='%s/package%s'"%(
-	escquotes(PYTHON), escquotes(OUTPUTDIR), escquotes(basedir)), 'r')
+	escquotes(PYTHON), escquotes(BUILDDIR), escquotes(basedir)), 'r')
 for ln in fd.xreadlines():
 	sys.stdout.write(ln)
 
+print "Copying readme and license"
+shutil.copyfile("ReadMe.txt", os.path.join(OUTPUTDIR, "ReadMe.txt"))
+shutil.copyfile("License.txt", os.path.join(OUTPUTDIR, "License.txt"))
+shutil.copyfile("ChangeLog", os.path.join(OUTPUTDIR, "ChangeLog"))
+
 print "Setting up developer templates"
 
-basedir = '%s/package'%(OUTPUTDIR)
-os.mkdir(os.path.join(basedir, 'Developer'))
-os.mkdir(os.path.join(basedir, 'Developer', 'ProjectBuilder Extras'))
-os.mkdir(os.path.join(basedir, 'Developer', 'ProjectBuilder Extras', 'Project Templates'))
-os.mkdir(os.path.join(basedir, 'Developer', 'ProjectBuilder Extras', 'Project Templates', 'Application'))
-
-destination = os.path.join(basedir, 'Developer', 'ProjectBuilder Extras', 'Project Templates', 'Application', 'Cocoa-Python Application')
-shutil.copytree('Project Templates/Cocoa-Python Application', destination)
-
-def findCVS(irrelevant, dirName, names):
-	if '.DS_Store' in names:
-		os.remove( os.path.join(dirName, '.DS_Store') )
+nastyFiles = ['.DS_Store', '.gdb_history']
+def killNasties(irrelevant, dirName, names):
+        for aName in names:
+                if aName in nastyFiles:
+                        os.remove( os.path.join(dirName, aName) )
+        if dirName.find(".pbproj") > 0:
+                for aName in names:
+                        if aName.find(".pbxuser") > 0:
+                                os.remove( os.path.join(dirName, aName) )
 	if dirName[-3:] == 'CVS':
 		while len(names): del names[0]
 		shutil.rmtree(dirName)
 
-os.path.walk(destination, findCVS, None)
+basedir = '%s/package'%(BUILDDIR)
+
+makeDir(basedir, 'Developer', 'ProjectBuilder Extras', 'Project Templates', 'Application')
+templateDestination = os.path.join(basedir, 'Developer', 'ProjectBuilder Extras',
+                                   'Project Templates', 'Application', 'Cocoa-Python Application')
+shutil.copytree('Project Templates/Cocoa-Python Application', templateDestination)
+
+print "Setting up developer examples"
+
+makeDir(basedir, 'Developer', 'Examples')
+examplesDestination = os.path.join(basedir, 'Developer', 'Examples', 'PyObjC')
+shutil.copytree('Examples', examplesDestination)
+
+os.path.walk(templateDestination, killNasties, None)
+os.path.walk(examplesDestination, killNasties, None)
 
 print 'Building package'
-pm = buildpkg.PackageMaker('PyObjC', package_version(), 
+pm = buildpkg.PackageMaker('PyObjC-%s' % package_version(), package_version(), 
 """\
 Python <-> Objective-C bridge that supports building full featured Cocoa
 applications.
 	OutputDir=os.path.join(os.getcwd(), OUTPUTDIR),
 	Version=package_version(),
 	NeedsAuthorization="YES",
-	Relocatable="NO")
+	Relocatable="NO",
+        RootVolumeOnly="YES")
 
 print "Done, don't forget to test the output!"
 # bundlebuilder test below).
 package_dir = dict([(pkg, 'Lib/' + pkg) for pkg in packages])
 
+for aPackage in package_dir.keys():
+        testDir = os.path.join(package_dir[aPackage], 'test')
+        if os.path.isdir(testDir):
+                packageName = '%s.test' % aPackage
+                package_dir[packageName] = testDir
+                packages.append(packageName)
+
 try:
     import bundlebuilder
 except ImportError:
     packages.append('')
     package_dir[''] = 'MPCompat'
 
-
 setup(name = "pyobjc",
       version = package_version(),
       description = "Python<->ObjC Interoperability Module",
Tip: Filter by directory path e.g. /media app.js to search for public/media/app.js.
Tip: Use camelCasing e.g. ProjME to search for ProjectModifiedEvent.java.
Tip: Filter by extension type e.g. /repo .js to search for all .js files in the /repo directory.
Tip: Separate your search with spaces e.g. /ssh pom.xml to search for src/ssh/pom.xml.
Tip: Use ↑ and ↓ arrow keys to navigate and return to view the file.
Tip: You can also navigate files with Ctrl+j (next) and Ctrl+k (previous) and view the file with Ctrl+o.
Tip: You can also navigate files with Alt+j (next) and Alt+k (previous) and view the file with Alt+o.