pyobjc-dev Mailing List for PyObjC (Page 293)
Brought to you by:
ronaldoussoren
You can subscribe to this list here.
2000 |
Jan
|
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
(9) |
---|---|---|---|---|---|---|---|---|---|---|---|---|
2001 |
Jan
(1) |
Feb
(2) |
Mar
(3) |
Apr
(30) |
May
(18) |
Jun
|
Jul
(4) |
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
2002 |
Jan
(7) |
Feb
(2) |
Mar
(1) |
Apr
|
May
|
Jun
(3) |
Jul
(13) |
Aug
|
Sep
(23) |
Oct
(180) |
Nov
(291) |
Dec
(95) |
2003 |
Jan
(338) |
Feb
(352) |
Mar
(97) |
Apr
(46) |
May
(226) |
Jun
(184) |
Jul
(145) |
Aug
(141) |
Sep
(69) |
Oct
(161) |
Nov
(96) |
Dec
(90) |
2004 |
Jan
(66) |
Feb
(87) |
Mar
(98) |
Apr
(132) |
May
(115) |
Jun
(68) |
Jul
(150) |
Aug
(92) |
Sep
(59) |
Oct
(52) |
Nov
(17) |
Dec
(75) |
2005 |
Jan
(84) |
Feb
(191) |
Mar
(133) |
Apr
(114) |
May
(158) |
Jun
(185) |
Jul
(62) |
Aug
(28) |
Sep
(36) |
Oct
(88) |
Nov
(65) |
Dec
(43) |
2006 |
Jan
(85) |
Feb
(62) |
Mar
(92) |
Apr
(75) |
May
(68) |
Jun
(101) |
Jul
(73) |
Aug
(37) |
Sep
(91) |
Oct
(65) |
Nov
(30) |
Dec
(39) |
2007 |
Jan
(24) |
Feb
(28) |
Mar
(10) |
Apr
(2) |
May
(18) |
Jun
(16) |
Jul
(21) |
Aug
(6) |
Sep
(30) |
Oct
(31) |
Nov
(153) |
Dec
(31) |
2008 |
Jan
(63) |
Feb
(70) |
Mar
(47) |
Apr
(24) |
May
(59) |
Jun
(22) |
Jul
(12) |
Aug
(7) |
Sep
(14) |
Oct
(26) |
Nov
(5) |
Dec
(5) |
2009 |
Jan
(10) |
Feb
(41) |
Mar
(70) |
Apr
(88) |
May
(49) |
Jun
(62) |
Jul
(34) |
Aug
(15) |
Sep
(55) |
Oct
(40) |
Nov
(67) |
Dec
(21) |
2010 |
Jan
(60) |
Feb
(17) |
Mar
(26) |
Apr
(26) |
May
(29) |
Jun
(4) |
Jul
(21) |
Aug
(21) |
Sep
(10) |
Oct
(12) |
Nov
(3) |
Dec
(19) |
2011 |
Jan
(3) |
Feb
(13) |
Mar
(8) |
Apr
(8) |
May
(17) |
Jun
(20) |
Jul
(21) |
Aug
(7) |
Sep
|
Oct
|
Nov
(9) |
Dec
(11) |
2012 |
Jan
(3) |
Feb
|
Mar
|
Apr
(5) |
May
(4) |
Jun
(14) |
Jul
(5) |
Aug
(2) |
Sep
(15) |
Oct
(2) |
Nov
(23) |
Dec
(1) |
2013 |
Jan
(8) |
Feb
(1) |
Mar
|
Apr
|
May
(5) |
Jun
(1) |
Jul
(5) |
Aug
(4) |
Sep
|
Oct
(12) |
Nov
(10) |
Dec
(3) |
2014 |
Jan
(7) |
Feb
(14) |
Mar
(2) |
Apr
|
May
(2) |
Jun
(11) |
Jul
(10) |
Aug
(4) |
Sep
|
Oct
(8) |
Nov
(1) |
Dec
(2) |
2015 |
Jan
(9) |
Feb
(7) |
Mar
(1) |
Apr
|
May
(7) |
Jun
|
Jul
(5) |
Aug
(6) |
Sep
|
Oct
(1) |
Nov
(4) |
Dec
|
2016 |
Jan
(1) |
Feb
(1) |
Mar
(4) |
Apr
(2) |
May
(1) |
Jun
|
Jul
(6) |
Aug
(8) |
Sep
(21) |
Oct
(17) |
Nov
|
Dec
(36) |
2017 |
Jan
(6) |
Feb
(2) |
Mar
(4) |
Apr
(2) |
May
|
Jun
|
Jul
(1) |
Aug
|
Sep
(1) |
Oct
|
Nov
(1) |
Dec
(6) |
2018 |
Jan
(2) |
Feb
(3) |
Mar
(3) |
Apr
(14) |
May
(2) |
Jun
(2) |
Jul
(4) |
Aug
(3) |
Sep
(6) |
Oct
(16) |
Nov
(1) |
Dec
(6) |
2019 |
Jan
(3) |
Feb
(1) |
Mar
|
Apr
|
May
|
Jun
|
Jul
(2) |
Aug
|
Sep
|
Oct
(6) |
Nov
|
Dec
|
2020 |
Jan
|
Feb
|
Mar
(1) |
Apr
|
May
(2) |
Jun
(1) |
Jul
(7) |
Aug
(1) |
Sep
(1) |
Oct
|
Nov
(2) |
Dec
(1) |
2021 |
Jan
(1) |
Feb
|
Mar
|
Apr
|
May
|
Jun
(2) |
Jul
|
Aug
(5) |
Sep
(1) |
Oct
|
Nov
(1) |
Dec
|
2023 |
Jan
|
Feb
|
Mar
|
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(2) |
Oct
|
Nov
|
Dec
|
2025 |
Jan
(2) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
From: Ronald O. <ous...@ci...> - 2002-11-02 22:13:14
|
On Saturday, Nov 2, 2002, at 17:54 Europe/Amsterdam, bb...@ma... wrote: > On Saturday, November 2, 2002, at 11:27 AM, Steven Majewski wrote: >> Has anyone been able to build pyobjc on 10.1.5 ? > > It won't build on 10.1.5 right now. To be more precize: The core objc module/package should build just fine, but the wrappers for functions in Cocoa contain 10.2 specific code. > >> Using the default compiler, it always seems to die while >> trying to compile register.m. > > Ugh-- shouldn't be doing that! Definitely a compiler bug. Does it fail due to the size of the file or for some other reason? If the compiler on 10.1.5 doesn't like the size of the file we could split it into smaller parts. > >> I saw some notes on the list about problems with the file being so >> large, so I tried using gcc3 to build ( Is this what's standard on >> 10.2 ? ) -- it compiles register.m without problem but runs into >> a load of errors later on. > > The automatically generated files have loads of references to 10.2 > specific variables and API. This could be fixed. > > All of the new-to-10.2 APIs are surrounded by #ifdef blocks and, as > such, could be conditionally removed. It would be a matter of: > > - augmenting the generation scripts to deal with this I'm not sure if the current scripts maintain enough state to make this easily possible. BTW. The current scripts were meant to be temporary: Just a quick hack to have something until I built the real wrappers (probably using bgen). I never got to the second step :-( > > - adding the generation scripts to the overall module build > process [Ronald indicated that there are bugs in the generator > scripts, but I don't know what they are]\ There's 1 buglet that I know of: The last time I generated new wrappers I had to manually remove a definition (IIRC a constant). I didn't check why this was necessary, but this is probably fixable by adding more #imports to one of the files. > > - passing the header files to be processed by the generators > through CPP with the appropriated -D flags to cause 10.1 or 10.2 > specific builds [or, simply build the 10.1 binaries on a 10.1 > machine]. I'd build the 10.1 binaries on a 10.1 machine, just in case a 10.2 build picks up some unwanted dependencies. And you'll have to test the binaries on 10.1 anyway, actually building doesn't take too much time. On the other hand: On 10.2 you can some pre-existing macros to hide 10.2 specific definitions, this should make it easier to build 10.1 and 10.2 binaries from one set of sources. Ronald |
From: Steven M. <sd...@ma...> - 2002-11-02 17:30:17
|
On Saturday, November 2, 2002, at 11:54 AM, bb...@ma... wrote: > On Saturday, November 2, 2002, at 11:27 AM, Steven Majewski wrote: >> Has anyone been able to build pyobjc on 10.1.5 ? > > It won't build on 10.1.5 right now. > >> Using the default compiler, it always seems to die while >> trying to compile register.m. > > Ugh-- shouldn't be doing that! Definitely a compiler bug. Since it goes away when I use gcc3, that's a pretty firm vote for compiler bug! > > The automatically generated files have loads of references to 10.2 > specific variables and API. This could be fixed. > Ah! The 10.2 specific references probably explain all of the other error messages -- I get a couple of pages of 'initializer is not a constant' , among others. I'll take a look at whether it's worth the effort of trying to generate a set of 10.1 fixes. ( Otherwise, I'm out for the duration! ) Thanks. -- Steve |
From: <bb...@ma...> - 2002-11-02 16:54:35
|
On Saturday, November 2, 2002, at 11:27 AM, Steven Majewski wrote: > Has anyone been able to build pyobjc on 10.1.5 ? It won't build on 10.1.5 right now. > Using the default compiler, it always seems to die while > trying to compile register.m. Ugh-- shouldn't be doing that! Definitely a compiler bug. > I saw some notes on the list about problems with the file being so > large, so I tried using gcc3 to build ( Is this what's standard on > 10.2 ? ) -- it compiles register.m without problem but runs into > a load of errors later on. The automatically generated files have loads of references to 10.2 specific variables and API. This could be fixed. All of the new-to-10.2 APIs are surrounded by #ifdef blocks and, as such, could be conditionally removed. It would be a matter of: - augmenting the generation scripts to deal with this - adding the generation scripts to the overall module build process [Ronald indicated that there are bugs in the generator scripts, but I don't know what they are] - passing the header files to be processed by the generators through CPP with the appropriated -D flags to cause 10.1 or 10.2 specific builds [or, simply build the 10.1 binaries on a 10.1 machine]. The last step isn't strictly necessary but might be nice in that it would allow 10.1 binaries to be build on a 10.2 machine. b.bum |
From: Steven M. <sd...@ma...> - 2002-11-02 16:27:47
|
Has anyone been able to build pyobjc on 10.1.5 ? Using the default compiler, it always seems to die while trying to compile register.m. I saw some notes on the list about problems with the file being so large, so I tried using gcc3 to build ( Is this what's standard on 10.2 ? ) -- it compiles register.m without problem but runs into a load of errors later on. -- Steve Majewski |
From: Bill B. <bb...@co...> - 2002-11-02 14:23:40
|
On Saturday, November 2, 2002, at 02:06 AM, Ronald Oussoren wrote: > On Saturday, Nov 2, 2002, at 05:25 Europe/Amsterdam, Bill Bumgarner > wrote: > >> The following is still broken when bridging ObjC objects into Python. >> I have added a unit test to test this in preparation to actually fix >> it (even though I have *no clue* how to fix it yet :-). >> >> >>> from Foundation import * >> >>> y = NSMutableArray.arrayWithArray_( range(0,10) ) >> >>> x = range(0,10) >> >>> x[1:3] = y >> Traceback (most recent call last): >> File "<stdin>", line 1, in ? >> TypeError: must assign list (not "NSCFArray") to slice >> >>> >> >> OK... so, how to fix? > I'll think about this. Some experimentation shows that 'y' must really > be a list, iterator objects also fail here. It might be usefull to ask > on comp.lang.python/pyt...@py... why this is so. Right -- in Python 2.2, it seems that one can add ListType as a base of something to have it act like a list. This works for all of the primitive types... >>> class foo(list): ... pass ... >>> x = foo() >>> x.append(1) >>> x [1] >>> type(x) <class '__main__.foo'> >>> x[0:1] [1] >>> y = [] >>> y = [1,2,3,4] >>> y[1] = x >>> y [1, [1], 3, 4] >>> type(y) <type 'list'> >>> type(y[1]) <class '__main__.foo'> >>> >> It looks like we could augment... >> >> PyObject* ObjCClass_New(Class objc_class) >> >> ... such that if.... >> >> [objc_class isKindOfClass: [NSArray class]] >> >> ... is true, then we add <type 'list'> to the bases for the newly >> created Python class object? Assuming a complete implementation of >> convenience methods, this would allow bridged instances of NSArray to >> function fully on the Python side of the bridge [i.e. work in >> contexts like the above where the runtime is testing for a particular >> type and not just a set of methods]. > I've check the implementation of this feature in Python 2.3 and the > code directly accesses the representation of 'y'. That explains why > the want a list object instead of a object that implements the list > interface. Appears to be by design... the language appears to be moving to type() as a means of effectively checking for conformance to a particular protocol or feature set. >> As an experiment, I tried-- naively-- to add this to the function >> that bridges classes to Python... it doesn't work. >> >> fprintf(stderr, "Adding.... %s\n\n", objc_class->name); >> if ( [objc_class respondsToSelector: >> @selector(isSubclassOfClass:)] && >> [objc_class isSubclassOfClass: objc_getClass("NSArray")] >> ) { >> _PyTuple_Resize(&bases, 2); >> PyTuple_SetItem(bases, 1, (PyObject*)&PyList_Type); >> Py_INCREF((&PyList_Type)); >> } >> >> ...... >> Adding.... NSArray >> >> Traceback (most recent call last): >> File "Lib/Foundation/test/test_nsexception.py", line 4, in ? >> from Foundation import * >> File "/usr/lib/python2.2/site-packages/Foundation/__init__.py", >> line 42, in ? >> class_list = >> load_bundle('/System/Library/Frameworks/Foundation.framework') >> File "/usr/lib/python2.2/site-packages/Foundation/__init__.py", >> line 37, in load_bundle >> classes = [ cls >> TypeError: multiple bases have instance lay-out conflict > > I suppose this is because both base-classes contain additional fields > in the C-struct: > struct PyListObject { // not the actual declaration! > PyObject_HEAD > PyObject** data; > }; > > struct ObjCObject { // not the actual declaration > PyObject_HEAD > id real_object; > }; > > The subclass would have to have a C struct that can be casted to > either one of these definitions. That would make sense. Reproducing in the interpreter -- first using objc, second in a new interpreter using nothing but Python classes. >>> from Foundation import * >>> class bar(NSMutableArray, list): ... pass ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: multiple bases have instance lay-out conflict >>> class x (list, dict): pass ... Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: multiple bases have instance lay-out conflict Hmmm... so, it appears that you can't have multiple compiled bases as a result. That seems like a rather nasty limitation-- what if I want to create a class that CAN act both as a dictionary and a list?? b.bum |
From: Ronald O. <ous...@ci...> - 2002-11-02 07:06:47
|
On Saturday, Nov 2, 2002, at 05:25 Europe/Amsterdam, Bill Bumgarner wrote: > The following is still broken when bridging ObjC objects into Python. > I have added a unit test to test this in preparation to actually fix > it (even though I have *no clue* how to fix it yet :-). > > >>> from Foundation import * > >>> y = NSMutableArray.arrayWithArray_( range(0,10) ) > >>> x = range(0,10) > >>> x[1:3] = y > Traceback (most recent call last): > File "<stdin>", line 1, in ? > TypeError: must assign list (not "NSCFArray") to slice > >>> > > OK... so, how to fix? I'll think about this. Some experimentation shows that 'y' must really be a list, iterator objects also fail here. It might be usefull to ask on comp.lang.python/pyt...@py... why this is so. > > It looks like we could augment... > > PyObject* ObjCClass_New(Class objc_class) > > ... such that if.... > > [objc_class isKindOfClass: [NSArray class]] > > ... is true, then we add <type 'list'> to the bases for the newly > created Python class object? Assuming a complete implementation of > convenience methods, this would allow bridged instances of NSArray to > function fully on the Python side of the bridge [i.e. work in contexts > like the above where the runtime is testing for a particular type and > not just a set of methods]. I've check the implementation of this feature in Python 2.3 and the code directly accesses the representation of 'y'. That explains why the want a list object instead of a object that implements the list interface. > As an experiment, I tried-- naively-- to add this to the function that > bridges classes to Python... it doesn't work. > > fprintf(stderr, "Adding.... %s\n\n", objc_class->name); > if ( [objc_class respondsToSelector: > @selector(isSubclassOfClass:)] && > [objc_class isSubclassOfClass: objc_getClass("NSArray")] > ) { > _PyTuple_Resize(&bases, 2); > PyTuple_SetItem(bases, 1, (PyObject*)&PyList_Type); > Py_INCREF((&PyList_Type)); > } > > ...... > Adding.... NSArray > > Traceback (most recent call last): > File "Lib/Foundation/test/test_nsexception.py", line 4, in ? > from Foundation import * > File "/usr/lib/python2.2/site-packages/Foundation/__init__.py", line > 42, in ? > class_list = > load_bundle('/System/Library/Frameworks/Foundation.framework') > File "/usr/lib/python2.2/site-packages/Foundation/__init__.py", line > 37, in load_bundle > classes = [ cls > TypeError: multiple bases have instance lay-out conflict I suppose this is because both base-classes contain additional fields in the C-struct: struct PyListObject { // not the actual declaration! PyObject_HEAD PyObject** data; }; struct ObjCObject { // not the actual declaration PyObject_HEAD id real_object; }; The subclass would have to have a C struct that can be casted to either one of these definitions. Ronald |
From: Bill B. <bb...@co...> - 2002-11-02 04:25:09
|
The following is still broken when bridging ObjC objects into Python. I have added a unit test to test this in preparation to actually fix it (even though I have *no clue* how to fix it yet :-). >>> from Foundation import * >>> y = NSMutableArray.arrayWithArray_( range(0,10) ) >>> x = range(0,10) >>> x[1:3] = y Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: must assign list (not "NSCFArray") to slice >>> OK... so, how to fix? It looks like we could augment... PyObject* ObjCClass_New(Class objc_class) ... such that if.... [objc_class isKindOfClass: [NSArray class]] ... is true, then we add <type 'list'> to the bases for the newly created Python class object? Assuming a complete implementation of convenience methods, this would allow bridged instances of NSArray to function fully on the Python side of the bridge [i.e. work in contexts like the above where the runtime is testing for a particular type and not just a set of methods]. As an experiment, I tried-- naively-- to add this to the function that bridges classes to Python... it doesn't work. fprintf(stderr, "Adding.... %s\n\n", objc_class->name); if ( [objc_class respondsToSelector: @selector(isSubclassOfClass:)] && [objc_class isSubclassOfClass: objc_getClass("NSArray")] ) { _PyTuple_Resize(&bases, 2); PyTuple_SetItem(bases, 1, (PyObject*)&PyList_Type); Py_INCREF((&PyList_Type)); } ...... Adding.... NSArray Traceback (most recent call last): File "Lib/Foundation/test/test_nsexception.py", line 4, in ? from Foundation import * File "/usr/lib/python2.2/site-packages/Foundation/__init__.py", line 42, in ? class_list = load_bundle('/System/Library/Frameworks/Foundation.framework') File "/usr/lib/python2.2/site-packages/Foundation/__init__.py", line 37, in load_bundle classes = [ cls TypeError: multiple bases have instance lay-out conflict Not sure what to do next.... b.bum |
From: Bill B. <bb...@co...> - 2002-11-02 04:17:17
|
Because the bridge converts strings as they go back and forth, there is no way to invoke certain methods on NSString. I.e. I can't (totally bogus example, yes, but there are uses for this stuff in other contexts -- -drawString:... immediately comes to mind): [bumbox:~/bbum-developer/sourceforge/pyobjc] bbum% python Python 2.2 (#1, 07/14/02, 23:25:09) [GCC Apple cpp-precomp 6.14] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> from Foundation import * >>> x = NSString.stringWithString_( "foo bar baz" ) >>> type(x) <type 'str'> >>> x.componentsSeparatedByString_( " " ) Traceback (most recent call last): File "<stdin>", line 1, in ? AttributeError: 'str' object has no attribute 'componentsSeparatedByString_' >>> NSString.componentsSeparatedByString_( x, " " ) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: First argument must be an objective-C object, got 'foo bar baz' If we moved to bridging strings in the same fashion as we bridge the various arrays and dictionaries, it should be possible to bridge both ways in a transparent fashion? Hmmm.... b.bum (thinking out loud) |
From: <bb...@ma...> - 2002-11-01 21:18:12
|
>> The key difference is in the information contained within the >> executable found within the app wrapper. In my solution, the >> executable automatically carries the information about what >> frameworks are used into the python interpreter by simply linking the >> custom executable against the appropriate frameworks. > > This bit I don't understand. First of all, if you are able to "carry > information about what frameworks are used into the python > interpreter": why would that only work if you exec() /usr/bin/python, > and not when you exec() ..../Contents/MacOS/python which is a symlink > to /usr/bin/python? Second, I don't understand how you carry this > information over. Once you exec() the running binary is blown out of > the air, and anything it is linked against disappears. And if the > carrying-over somehow happens through open files, or argv[0] or some > such it will work just as well in "my" scheme.... The symlink would work fine except for the implied fragility. If it is just a symlink to /usr/bin/python, it isn't a problem. If it is a symlink to an alternative python binary somewhere, it'll blow up on some user's systems (but will be useful in the development environment). I added some comments to the source and have included it... it is relatively self explanatory. The main() -- the Main.py file follows (it'll be renamed __main__.py in the near future). int pyobjc_main(int argc, char * const *argv, char * const *envp) { [[NSAutoreleasePool alloc] init]; // never released, execve() overlays the process const char **childArgv = alloca(sizeof(char *) * (argc + 5)); char **childEnvp = (char **)envp; const char *pythonBinPathPtr; const char *mainPyPathPtr; NSEnumerator *bundleEnumerator = [[NSBundle allFrameworks] reverseObjectEnumerator]; NSBundle *aBundle; NSBundle *mainBundle = [NSBundle mainBundle]; NSMutableArray *bundlePaths = [NSMutableArray array]; int i; // 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]; for(i=0; envp[i]; i++); childEnvp = malloc( sizeof(char *) * (i+5) ); bcopy( envp, childEnvp, ( i * sizeof(char *) ) ); childEnvp[i++] = (char *)dyldFrameworkPath; childEnvp[i++] = (char *)dyldLibraryPath; //! childEnvp[i++] = "DYLD_NO_FIX_PREBINDING=1"; Can't decide if this is a good idea. // 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; } // 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"; pythonBinPathPtr = [pythonBinPath UTF8String]; // figure out the entry point -- all this goes away as it will be standardized on __main__.py NSString *mainPyFile = [[mainBundle infoDictionary] objectForKey: @"PrincipalPythonFile"]; NSString *mainPyPath = nil; if (mainPyFile) mainPyPath = [mainBundle pathForResource: mainPyFile ofType: nil]; if ( !mainPyPath ) mainPyPath = [mainBundle pathForResource: @"Main.py" ofType: nil]; if ( !mainPyPath ) [NSException raise: NSInternalInconsistencyException format: @"%s:%d pyobjc_main() Failed to find main python entry point for application. Exiting.", __FILE__, __LINE__]; mainPyPathPtr = [mainPyPath UTF8String]; // construct argv for the child // 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]; // path to the python file that acts as the main entry point childArgv[1] = mainPyPathPtr; // pass original arguments (such as -NSOpen) verbatum for (i = 1; i<argc; i++) childArgv[i+1] = argv[i]; // add an argument that lists all frameworks childArgv[i+1] = "-PyFrameworkPaths"; childArgv[i+2] = [[bundlePaths componentsJoinedByString: @":"] UTF8String]; // terminate the arg list childArgv[i+3] = NULL; // print a nice debugging helper message, if enabled 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 return execve(pythonBinPathPtr, (char **)childArgv, childEnvp); } int main(int argc, char * const *argv, char * const *envp) { return pyobjc_main(argc, argv, envp); } Add a Main.py: # # 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")) del sys.argv[0] # # Import the components of the Python<->ObjC bridge. # 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], ":") del sys.argv[ pyFrameworkPathsIndex : pyFrameworkPathsIndex + 2 ] 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. # ..... # # 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) ) |
From: <bb...@ma...> - 2002-11-01 21:05:16
|
On Friday, November 1, 2002, at 03:06 PM, Ronald Oussoren wrote: > On Friday, Nov 1, 2002, at 15:55 Europe/Amsterdam, bb...@ma... wrote: >> On Friday, November 1, 2002, at 07:05 AM, Jack Jansen wrote: >> I think we are talking about two different ways of building >> applications. > > ... and I'd like to suppport either way of building applications, if > only because I've vi keyboard commands hardwired into my hands (I tend > to insert sequences of j/k/l/h into when I'm really concentrated while > typing in a GUI editor :-) Thank goodness the AppKit folks were emacs-heads... I have emacs wired in my head and still save documents in Project Builder via C-xC-s half the time. In any case, I totally agree that supporting both ways of building apps should be a priority. >>> On vrijdag, nov 1, 2002, at 03:53 Europe/Amsterdam, bb...@ma... >>> wrote: >>>> On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: >>>>> On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... >>>>> wrote: >>>>>> .... >>>>>> Note that there is no python binary in the app wrapper, only a >>>>>> symlink to one. The *only* substantial difference between the two >>>>>> scheme's is that in Jack's version argv[0] is (a) not the >>>>>> CFBundleExecutable (but still a file located in Contents/MacOS in >>>>>> the application bundle) and (b) sys.executable is automaticly a >>>>>> python interpreter. > > Another minor difference is that is harder to switch interpreters, but > I'd tend to find this an advantage (but hey, I can change the > main-bin-python.m file to not support NSUserDefaults making this a > very minor difference). Switching interpreters should really only be an issue in the developer environment. Once an app is switched, it'll either be hardwired to Apple's interpreter or will have to ship with an alternative interpreter (or require the user to install one). >> The key difference is in the information contained within the >> executable found within the app wrapper. In my solution, the >> executable automatically carries the information about what >> frameworks are used into the python interpreter by simply linking the >> custom executable against the appropriate frameworks. This also >> allows the developer to work directly with the Project Builder >> indices -- for example, If I write "bundle = >> NSBundle.bundleWithPath_(path)", I can command-double-click on the >> word NSBundle and Project Builder takes me straight to the >> declaration for NSBundle (option-double-click displays the >> documentation). > I see the usefulness of using documentation from PB, but the week was > probably slightly too long for me because I fail to see the > usefullness of actually passing information about linked frameworks to > the Python script: You still have to write a wrapper module for the > frameworks, unless you intend to locate all classes by using > objc.lookup_class. Typically, I haven't had to write a wrapper module for the frameworks in those projects where I have custom frameworks built into the application wrapper. The frameworks may be composed of Obj-C code that the python code never directly refers to (in my case, a couple of window controllers that set up some table views with some custom NSCell subclasses). Another advantage to linking the frameworks into the custom executable in the app wrapper [with the autoloading mechanism] is that it enables automatic prebinding. The frameworks are built with an install_name of @executable_path/../Frameworks/* (as required by frameworks encapsulated in an app wrapper). The automatic prebinding on 10.2 picks this up and re-prebinds the frameworks, as needed. The unfortunate side effect is that a couple of environment variables must be propagated prior to loading the frameworks, but that will always be the case if (a) the frameworks are to be dynamically loaded by the interpreter and (b) one framework links against the other. Actually, come to think of it, the only way to use frameworks with the python command line interpreter where one framework links against another and the two frameworks are included in the app wrapper is to use execve() to pass control to the interpreter as the DYLIB environment variables must be set before the executable is launched! (This'll all probably make very little sense to anyone but the folks that have been down that particularly painful path.) >>> I would think this works the same as Bills scheme, with the only >>> exception that sys.executable points to a python interpreter, so >>> something like system(sys.executable + " myscript.py") will work. >> >> Two solutions: >> >> (1) In Main.py (or __main__.py -- is that "more standard"?), set >> sys.executable to whatever python interpreter the user has selected >> (in my solution, that would mean reading the 'PythonBinPath' user >> default in a similar fashion as the bootstrap executable). > BuildApplication/BuildApplet in MacPython name the principle python > file in the created application __main__.py, I suppose because the > __main__ is the name of the 'toplevel' module and can therefore not be > used for normal code (e.g. you cannot accidently overwrite a module > when renaming the principle python file to __main__.py). Works for me. I'll change it as I have a chance. >> (2) Make it such that the second invocation of sys.executable >> [which points to the bootstrap binary in my app wrapper] simply calls >> execve() with a command line that passes control to python along with >> the arguments. I.e. put recursion protection on that executable. >> The overhead of an extra execve() is trivial in comparison to the >> overhead of a full blown GUI. > This sounds pretty ugly. Actually implementing this correctly is hard, > unless you implement the wrappper in python. Wwwweeeeelllll.... it could be done by setting an environment variable before the call to execve(). If that environment variable is set, it would do the pass-straight-to-python-interpreter style execve(). Of course, if someone were to fork out and subshell to another GUI app directly, it'd break -- but, then again, you aren't supposed to invoke GUI apps in this fashion anyway. Yes, ugly. Hard. Yuck. b.bum |
From: Jack J. <Jac...@or...> - 2002-11-01 21:02:47
|
On vrijdag, november 1, 2002, at 03:55 , bb...@ma... wrote: > On Friday, November 1, 2002, at 07:05 AM, Jack Jansen wrote: >>> - The python sources are copied to the Resources >>> directory of the application >>> >>> Do we have any control over this? I'd like to be able to >>> convert the sources to bytecode (slightly faster startup, and >>> this makes it harder to change the code). >> Please have a look at BuildApplication (and the underlying >> freeze modules), so you don't go reinventing the wheel. >> BuildApplication first recursively collects all modules used >> by a script, then byte-compiles these and then stuffs them >> into OS9 resources. The last step needs to be modified for >> OSX, but the first step (which is basically shared with >> freeze) can definitely be used. > > I think we are talking about two different ways of building > applications. Yes, after reading Ronald's original message again I think I did misunderstand it. I thought the discussion was about including and precompiling all the stuff you need (including standard modules, stuff from site-python, etc), but it was only about precompiling the "private" stuff. Sorry. >> On vrijdag, nov 1, 2002, at 03:53 Europe/Amsterdam, >> bb...@ma... wrote: >>> On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: >>>> On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, >>>> bb...@ma... wrote: >>>>> ..... >> I think there's a misunderstanding somewhere in the >> me->ronald->bill conversation, as I don't see why Bill's >> method would be different from mine. In other words, please >> explain if there is... >> >> Here's my scheme, with an example: >> /Applications/foo.app/Contents/MacOS/foo looks for __main__.py >> in Resources, and does >> execve("/Applications/foo.app/Contents/MacOS/python", >> ["/Applications/foo.app/Contents/MacOS/python", >> "/Applications/foo.app/Contents/Resources/__main__.py", >> rest of original argv]) >> and Contents/MacOS/python is a symlink to /usr/bin/python. > > In terms of passing control to the python interpreter, the two > solutions are doing same thing excepting for the symlink and > the direct insertion of the python binary into the app wrapper. As Ronald already explained there's only a symlink. > > The key difference is in the information contained within the > executable found within the app wrapper. In my solution, the > executable automatically carries the information about what > frameworks are used into the python interpreter by simply > linking the custom executable against the appropriate > frameworks. This bit I don't understand. First of all, if you are able to "carry information about what frameworks are used into the python interpreter": why would that only work if you exec() /usr/bin/python, and not when you exec() ..../Contents/MacOS/python which is a symlink to /usr/bin/python? Second, I don't understand how you carry this information over. Once you exec() the running binary is blown out of the air, and anything it is linked against disappears. And if the carrying-over somehow happens through open files, or argv[0] or some such it will work just as well in "my" scheme.... [...] > (2) Make it such that the second invocation of > sys.executable [which points to the bootstrap binary in my app > wrapper] simply calls execve() with a command line that passes > control to python along with the arguments. Now you have me completely confused. How would the wrapper know it is invoked for a second time? And how would this be different from a completely unrelated call to the applet? > -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: Ronald O. <ous...@ci...> - 2002-11-01 20:06:12
|
On Friday, Nov 1, 2002, at 15:55 Europe/Amsterdam, bb...@ma... wrote: > On Friday, November 1, 2002, at 07:05 AM, Jack Jansen wrote: >>> - The python sources are copied to the Resources directory of >>> the application >>> >>> Do we have any control over this? I'd like to be able to convert the >>> sources to bytecode (slightly faster startup, and this makes it >>> harder to change the code). >> Please have a look at BuildApplication (and the underlying freeze >> modules), so you don't go reinventing the wheel. BuildApplication >> first recursively collects all modules used by a script, then >> byte-compiles these and then stuffs them into OS9 resources. The last >> step needs to be modified for OSX, but the first step (which is >> basically shared with freeze) can definitely be used. > > I think we are talking about two different ways of building > applications. ... and I'd like to suppport either way of building applications, if only because I've vi keyboard commands hardwired into my hands (I tend to insert sequences of j/k/l/h into when I'm really concentrated while typing in a GUI editor :-) > >> On vrijdag, nov 1, 2002, at 03:53 Europe/Amsterdam, bb...@ma... >> wrote: >>> On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: >>>> On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... >>>> wrote: >>>>> ..... >> I think there's a misunderstanding somewhere in the me->ronald->bill >> conversation, as I don't see why Bill's method would be different >> from mine. In other words, please explain if there is... >> >> Here's my scheme, with an example: >> /Applications/foo.app/Contents/MacOS/foo looks for __main__.py in >> Resources, and does >> execve("/Applications/foo.app/Contents/MacOS/python", >> ["/Applications/foo.app/Contents/MacOS/python", >> "/Applications/foo.app/Contents/Resources/__main__.py", >> rest of original argv]) >> and Contents/MacOS/python is a symlink to /usr/bin/python. > > In terms of passing control to the python interpreter, the two > solutions are doing same thing excepting for the symlink and the > direct insertion of the python binary into the app wrapper. Note that there is no python binary in the app wrapper, only a symlink to one. The *only* substantial difference between the two scheme's is that in Jack's version argv[0] is (a) not the CFBundleExecutable (but still a file located in Contents/MacOS in the application bundle) and (b) sys.executable is automaticly a python interpreter. Another minor difference is that is harder to switch interpreters, but I'd tend to find this an advantage (but hey, I can change the main-bin-python.m file to not support NSUserDefaults making this a very minor difference). A minor variation on Jack's scheme would be to make the CFBundleExecutable a python script: #!/usr/bin/env python import sys print sys.executable This prints /usr/local/bin/python or /usr/bin/python on my system (depending on the value of PATH). You'd of course loose the advantage of linking with the needed frameworks. This would also make it harder to use an application-local Python installation, which is more problematic. > > The key difference is in the information contained within the > executable found within the app wrapper. In my solution, the > executable automatically carries the information about what frameworks > are used into the python interpreter by simply linking the custom > executable against the appropriate frameworks. This also allows the > developer to work directly with the Project Builder indices -- for > example, If I write "bundle = NSBundle.bundleWithPath_(path)", I can > command-double-click on the word NSBundle and Project Builder takes me > straight to the declaration for NSBundle (option-double-click displays > the documentation). I see the usefulness of using documentation from PB, but the week was probably slightly too long for me because I fail to see the usefullness of actually passing information about linked frameworks to the Python script: You still have to write a wrapper module for the frameworks, unless you intend to locate all classes by using objc.lookup_class. > >> I would think this works the same as Bills scheme, with the only >> exception that sys.executable points to a python interpreter, so >> something like system(sys.executable + " myscript.py") will work. > > Two solutions: > > (1) In Main.py (or __main__.py -- is that "more standard"?), set > sys.executable to whatever python interpreter the user has selected > (in my solution, that would mean reading the 'PythonBinPath' user > default in a similar fashion as the bootstrap executable). BuildApplication/BuildApplet in MacPython name the principle python file in the created application __main__.py, I suppose because the __main__ is the name of the 'toplevel' module and can therefore not be used for normal code (e.g. you cannot accidently overwrite a module when renaming the principle python file to __main__.py). > > (2) Make it such that the second invocation of sys.executable > [which points to the bootstrap binary in my app wrapper] simply calls > execve() with a command line that passes control to python along with > the arguments. I.e. put recursion protection on that executable. The > overhead of an extra execve() is trivial in comparison to the overhead > of a full blown GUI. This sounds pretty ugly. Actually implementing this correctly is hard, unless you implement the wrappper in python. Ronald |
From: <bb...@ma...> - 2002-11-01 15:35:21
|
On Friday, November 1, 2002, at 07:05 AM, Jack Jansen wrote: >> - The python sources are copied to the Resources directory of >> the application >> >> Do we have any control over this? I'd like to be able to convert the >> sources to bytecode (slightly faster startup, and this makes it >> harder to change the code). > Please have a look at BuildApplication (and the underlying freeze > modules), so you don't go reinventing the wheel. BuildApplication > first recursively collects all modules used by a script, then > byte-compiles these and then stuffs them into OS9 resources. The last > step needs to be modified for OSX, but the first step (which is > basically shared with freeze) can definitely be used. I think we are talking about two different ways of building applications. The BuildApplication script, if I understand it correctly, builds an application without using any of the OS X development tools-- at least, none of the GUI level tools. The second means of building applications-- and the one that Ronald was asking about-- uses Project Builder to manage and build the application in the same fashion as a normal project. Having the ability to build standalone Cocoa-Python (or Carbon-Python) applications via BuildApplication and the MacPython IDE is certainly a very attractive feature -- it would be nice to be able to ship a "non-developer's development environment" that would work entirely standalone and on machines that do not otherwise have the development tools installed! In any case, I had a look at how to automatically compile all of the code in the app wrapper. It turned out to be even easier than expected and revealed a very powerful feature of Project Builder. - add a "Shell Script Build Phase" as the last build phase of the app target (select the last build phase before you add the new phase and it'll be added at the end) - check the 'run only when installing' box - set the shell to '/usr/bin/python' - set the script to: from os import * from os.path import * import compileall, re, sys def head(p): h, t = split(p) if h: p = head(h) return p appPath = join( environ['INSTALL_DIR'], head( environ['INNER_PRODUCT_SUBPATH']) ) compileall.compile_dir(appPath, rx=re.compile('pyobjc')) This will recompile the python code found within the app wrapper, but skip the 'pyobjc' subdirectory (since it is already compiled). That's it! Doing the same during a regular build requires using a different set of environment variables. You might want to 'print os.environ' to see what is available (make sure you have the build logging preference in Project Builder set to maximum verbosity). Removing the .py files from the appPath would be an easy addition. > On vrijdag, nov 1, 2002, at 03:53 Europe/Amsterdam, bb...@ma... wrote: >> On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: >>> On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... >>> wrote: >>>> ..... > I think there's a misunderstanding somewhere in the me->ronald->bill > conversation, as I don't see why Bill's method would be different from > mine. In other words, please explain if there is... > > Here's my scheme, with an example: > /Applications/foo.app/Contents/MacOS/foo looks for __main__.py in > Resources, and does > execve("/Applications/foo.app/Contents/MacOS/python", > ["/Applications/foo.app/Contents/MacOS/python", > "/Applications/foo.app/Contents/Resources/__main__.py", > rest of original argv]) > and Contents/MacOS/python is a symlink to /usr/bin/python. In terms of passing control to the python interpreter, the two solutions are doing same thing excepting for the symlink and the direct insertion of the python binary into the app wrapper. The key difference is in the information contained within the executable found within the app wrapper. In my solution, the executable automatically carries the information about what frameworks are used into the python interpreter by simply linking the custom executable against the appropriate frameworks. This also allows the developer to work directly with the Project Builder indices -- for example, If I write "bundle = NSBundle.bundleWithPath_(path)", I can command-double-click on the word NSBundle and Project Builder takes me straight to the declaration for NSBundle (option-double-click displays the documentation). One of the disadvantages of carrying along the python interpreter within the app wrapper is that it requires an entire python distribution to be carried along or there is the potential for a version mismatch. The alternative is to use a symlink to /usr/bin/python -- now that Apple ships python with the system, this shouldn't cause any problems but a symlink to some other interpreter becomes an issue. In any case, all of this is just compensation for the lack of embeddable interpreter shipping w/OS X [at least, AFAICT]. > I would think this works the same as Bills scheme, with the only > exception that sys.executable points to a python interpreter, so > something like system(sys.executable + " myscript.py") will work. Two solutions: (1) In Main.py (or __main__.py -- is that "more standard"?), set sys.executable to whatever python interpreter the user has selected (in my solution, that would mean reading the 'PythonBinPath' user default in a similar fashion as the bootstrap executable). (2) Make it such that the second invocation of sys.executable [which points to the bootstrap binary in my app wrapper] simply calls execve() with a command line that passes control to python along with the arguments. I.e. put recursion protection on that executable. The overhead of an extra execve() is trivial in comparison to the overhead of a full blown GUI. b.bum |
From: Jack J. <Jac...@or...> - 2002-11-01 12:05:17
|
> - The python sources are copied to the Resources directory of > the application > > Do we have any control over this? I'd like to be able to convert the > sources to bytecode (slightly faster startup, and this makes it harder > to change the code). Please have a look at BuildApplication (and the underlying freeze modules), so you don't go reinventing the wheel. BuildApplication first recursively collects all modules used by a script, then byte-compiles these and then stuffs them into OS9 resources. The last step needs to be modified for OSX, but the first step (which is basically shared with freeze) can definitely be used. This is on my todo list, but it's fairly far down, so feel free to beat me to it. On vrijdag, nov 1, 2002, at 03:53 Europe/Amsterdam, bb...@ma... wrote: > On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: >> On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... >> wrote: >>>> 2. If not, how could this be implemented? >>> >>> It is is implemented by: >> - The python sources are copied to the Resources directory of >> the application >> >> Do we have any control over this? I'd like to be able to convert the >> sources to bytecode (slightly faster startup, and this makes it >> harder to change the code). > > Sure. > > - Add a new shell script build phase to your project > > - check off the 'Run only when installing' checkbox > > - set the script to the command necessary to compile the python code > [see the PBX docs for what variables are available, etc...] > > The alternative is to do a new target of type legacy makefile, then > create another target named packaging and add both the app target and > the legacy target to packaging. The legacy target could be used to > compile all py files upon installation. This is how the Web Services > Tool project works -- if you 'pbxbuild install -target Packaging', it > uses a legacy makefile target to copy the readme and license to the > destination directory. With the addition of a script written by Mike > Trent and I, the whole thing can be automatically shoved onto a Disk > Image automatically. > >>> - using a series of copy file phases to copy the PyObjC module >>> into the 'pyobjc' subdirectory of the Resources directory of the >>> application when the 'install' target is used ('pbxbuild install' >>> from the command line). >>> >>> - the main.m uses execve() to transfer control to >>> /usr/bin/python and exec Main.py in a fashion where OS X thinks that >>> /usr/bin/python is the executable within the app wrapper (otherwise, >>> mainBundle breaks). Unfortunately, this is what breaks gdb. >>> Fortunately, this will go away when Apple ships a new build of >>> Python that includes a library for embedding. >> In a conversation about an 'addon-for-Apple-python' version of >> MacPython I mentioned this technique to Jack Jansen (the MacPython >> maintainer). He intends to use a slightly different technique: The >> wrapper does not use execve() /usr/bin/python, but a python binary(*) >> in the Contents/MacOS directory of the .app with and argv[0] that >> actually points to this python binary. The reason for this variation >> is that this would make 'sys.executable' point to a python >> interpreter and appearantly some existing code expects this >> (including the Python testsuite). We didn't know if the APIs that >> require a full path to the application in argv[0] would mind that >> argv[0] is not the name of the binary mentioned in the Info.plist. > > That'll work though the current use of execve() has a distinct > advantage (and, in reality, calling execve to transfer control to the > python interpreter adds very little overhead). > > The advantage to the current method is that the binary contained in > the app wrapper can be linked against all the frameworks that should > be loaded into the python interpreter environment; including any > frameworks specifically built for the project. The main that is in > Web Services Tool and-- now-- the Project Template passes the set of > frameworks linked into the app wrapper's executable into the execution > of the python binary as an argument. This argument is picked up by > Main.py and it automatically dynamically loads all of the frameworks > and executes an Init.py in each, if present. > > In other words, the app wrapper automatically bootstraps the python > environment with all of the frameworks that would normally be linked > directly into the application -- the developer doesn't have to do > anything to cause these frameworks to be loaded. I think there's a misunderstanding somewhere in the me->ronald->bill conversation, as I don't see why Bill's method would be different from mine. In other words, please explain if there is... Here's my scheme, with an example: /Applications/foo.app/Contents/MacOS/foo looks for __main__.py in Resources, and does execve("/Applications/foo.app/Contents/MacOS/python", ["/Applications/foo.app/Contents/MacOS/python", "/Applications/foo.app/Contents/Resources/__main__.py", rest of original argv]) and Contents/MacOS/python is a symlink to /usr/bin/python. I would think this works the same as Bills scheme, with the only exception that sys.executable points to a python interpreter, so something like system(sys.executable + " myscript.py") will work. -- - Jack Jansen <Jac...@or...> http://www.cwi.nl/~jack - - If I can't dance I don't want to be part of your revolution -- Emma Goldman - |
From: Ronald O. <ous...@ci...> - 2002-11-01 06:54:53
|
On Friday, Nov 1, 2002, at 06:33 Europe/Amsterdam, Stephen Steiner wrote: > I'd answer the 'what do we need to do' by: > > First and foremost documenting the 'holes not to fall into'. What > hasn't worked most often? What is the solution to having fallen into > each of the holes? This is a very good question, which I can't really answer. The holes I fall into tend to get filled pretty soon. The only 'hole' I know of right now is 'which python do I use to install PyObjC, and which one to actually run it'. If you use PB and have installed a custom Python (/usr/local/bin/python, /sw/bin/python .../) the two might not be the same if you use 'python setup.py install' to install PyObjC. The only important bug is IMHO the automatic processing of retain/release/autorelease in combination with methods that transfer object ownership to the caller and in combination with 'init...' methods that just remove the object when initialisation fails (e.g. NSDictionary.initFromFile_) Reference counting in the PyObjC implementation is also not 100% correct, I'm pretty sure that the Python refcounts of some objects are too high. I'll have to carefully check the code for this. Some other work left for 1.0: - Complete the work on Lib/objc/_convenience.py We're slowly adding more methods that make NS<Collection> classes act more like their Python counterparts, but this is not yet 100% complete (at least not the last time I looked at it) - Complete the wrappers for constants and global functions in Cocoa Constants should be picked up automaticly, but someone should check that we really have all values. Some global variables that are currently added as constants might really be variable, if so special wrapper functions should be added. Not all functions in Cocoa are wrapped at the moment. Most of these require manual work (nothing complex, just more information than available to the generator script) For bonus points: The wrappers should also compile on OSX 10.1. For more bonus points: The generator script isn't very robust, and currently needs manual fixup of the output. Fix this, or replace by a better script. - Complete custom wrappers for complex methods Some methods have pointer arguments or return pointers. If the pointer arguments are pass-by-reference arguments nothing has to be done, otherwise it is necessary to write custom method wrappers for the method. - Maybe port to GNUstep I'd like to see a GNUstep port in the future, but IMHO this is not something that is really required for 1.0 Ronald |
From: Stephen S. <sst...@ma...> - 2002-11-01 05:33:30
|
First let me say good job! I appreciate all the work you and others have done on this extremely valuable product. What is here works extremely well -- once it's set up and the user understands (somewhat) what is going on. I am looking forward to helping get this to be a 'product' we can all use and enjoy. I'd answer the 'what do we need to do' by: First and foremost documenting the 'holes not to fall into'. What hasn't worked most often? What is the solution to having fallen into each of the holes? A simple 'validation of installation' that just pokes all of the parts that have been most troublesome for users. Make sure that the installation is setup correctly. Clean up the examples, as you said, so that they work with the current version. Maybe add a 'runall' type script to produce a 'test suite' for now. Docs would be next. That's my opinion, for what it's worth... Steve |
From: <bb...@ma...> - 2002-11-01 04:52:16
|
On Thursday, October 31, 2002, at 11:44 PM, bb...@ma... wrote: > So much possibility, so little time.... Continuing this into a new thread. What do we need to do for a relatively immediate 1.0a1 [i.e. 0.7.1] release? I feel we can get by with something close to what we have-- what is in the repository right now works *really* well if you know what holes not to fall into. In particular, focus on cleaning up the examples a bit to be in line with the latest version of the module while letting the documentation slide for the moment [to be fixed as we move into beta]. What major bugs are outstanding [at the least, I would like to document 'em via unit tests for now] and what needs to be done? (I need to review the whole documentation thing, but SimTex sounds like the way to go...) b.bum |
From: <bb...@ma...> - 2002-11-01 04:44:20
|
On Thursday, October 31, 2002, at 04:52 PM, Ronald Oussoren wrote: > That's it, nibwrapper.py was not in the list. I've added it manually > and > after rebuilding the latest version of PyObjC with /usr/bin/python > TableModel2 worked correctly again. I updated the source and had a look at the project. nibwrapper.py was listed both in 'Bundle Resources' and in the 'Copy Files' phase. I'd bet PBX had added the file to the 'Copy Files' phase and not the 'Bundle Resources' phase when nibwrapper.py was originally added-- PBX can be confusing like that sometimes. In any case, it would have worked on installation, but fails during a normal build (because the copy files phase only happens during installation with the assumption that a developer machine will have PyObjC installed in the local python distribution). What we really need is a 'rapid turnaround mode' that adds the PBX project's directory to sys.path automatically. WebObjects does this automatically, but the mechanism by which it does so is, well, ummm..., "very interesting". Ideally, a project could have all of the Python files in a 'Copy Files' phase that is only activated on the 'install' target. Prior to that, everything would be found within the project... So much possibility, so little time.... b.bum |
From: <bb...@ma...> - 2002-11-01 02:53:29
|
On Thursday, October 31, 2002, at 04:42 PM, Ronald Oussoren wrote: > On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... > wrote: >>> 2. If not, how could this be implemented? >> >> It is is implemented by: > - The python sources are copied to the Resources directory of > the application > > Do we have any control over this? I'd like to be able to convert the > sources to bytecode (slightly faster startup, and this makes it harder > to change the code). Sure. - Add a new shell script build phase to your project - check off the 'Run only when installing' checkbox - set the script to the command necessary to compile the python code [see the PBX docs for what variables are available, etc...] The alternative is to do a new target of type legacy makefile, then create another target named packaging and add both the app target and the legacy target to packaging. The legacy target could be used to compile all py files upon installation. This is how the Web Services Tool project works -- if you 'pbxbuild install -target Packaging', it uses a legacy makefile target to copy the readme and license to the destination directory. With the addition of a script written by Mike Trent and I, the whole thing can be automatically shoved onto a Disk Image automatically. >> - using a series of copy file phases to copy the PyObjC module >> into the 'pyobjc' subdirectory of the Resources directory of the >> application when the 'install' target is used ('pbxbuild install' >> from the command line). >> >> - the main.m uses execve() to transfer control to /usr/bin/python >> and exec Main.py in a fashion where OS X thinks that /usr/bin/python >> is the executable within the app wrapper (otherwise, mainBundle >> breaks). Unfortunately, this is what breaks gdb. Fortunately, this >> will go away when Apple ships a new build of Python that includes a >> library for embedding. > In a conversation about an 'addon-for-Apple-python' version of > MacPython I mentioned this technique to Jack Jansen (the MacPython > maintainer). He intends to use a slightly different technique: The > wrapper does not use execve() /usr/bin/python, but a python binary(*) > in the Contents/MacOS directory of the .app with and argv[0] that > actually points to this python binary. The reason for this variation > is that this would make 'sys.executable' point to a python interpreter > and appearantly some existing code expects this (including the Python > testsuite). We didn't know if the APIs that require a full path to the > application in argv[0] would mind that argv[0] is not the name of the > binary mentioned in the Info.plist. That'll work though the current use of execve() has a distinct advantage (and, in reality, calling execve to transfer control to the python interpreter adds very little overhead). The advantage to the current method is that the binary contained in the app wrapper can be linked against all the frameworks that should be loaded into the python interpreter environment; including any frameworks specifically built for the project. The main that is in Web Services Tool and-- now-- the Project Template passes the set of frameworks linked into the app wrapper's executable into the execution of the python binary as an argument. This argument is picked up by Main.py and it automatically dynamically loads all of the frameworks and executes an Init.py in each, if present. In other words, the app wrapper automatically bootstraps the python environment with all of the frameworks that would normally be linked directly into the application -- the developer doesn't have to do anything to cause these frameworks to be loaded. In the production app that I'm working on that uses PyObjC, the automatic linking of the frameworks has proved to be a huge time saver. "It just works". In particular, it means that PBX's indexing features and everything about the build process work exactly like a normal Cocoa app save for the funky main file. Debugging only requires one extra step; an 'attach PID' command issued to a gdb session against /usr/bin/python -- there is a default you can set [found in main.m] that causes the app to actually print the gdb command needed to debug the app. In any case, argv[0] *must* be the path to the executable within the app wrapper or else the NSBundle/CFBundle environment will not be correctly initialized. --- Keep in mind that all of this is nothing but a workaround needed if using Apple's python. When using the Fink or framework builds, it is possible to simply embed the interpreter directly into the executable found within the app wrapper, thereby completely obviating the need to do any of this goofy execve() or sym linking or providing the python executable garbage that we are doing now. With an embedded interpreter, the launch times drop to normal, custom classes are linked directly into the executable, and debugging works exactly as it does with any other Cocoa application. With some serious trickery, we can actually support both execution models from the same executable as long as all of the custom classes are pushed into frameworks... at least, I'm pretty damned sure we can... it'll require some low level hacquery for which I have neither the need or whiskey to tackle right now. Have a look at the "other" main.m that is provided in the Web Services Tool example; it was the original version that I wrote for use with an embedded interpreter. In particular, it programmatically sets sys.executable as a part of the interpreter initialization. It is a far better solution than anything involving execve() or symlinks to python interpreters. b.bum |
From: Ronald O. <ous...@ci...> - 2002-10-31 21:52:08
|
On Thursday, Oct 31, 2002, at 22:30 Europe/Amsterdam, bb...@ma... wrote: > PBX is confusing, but amazingly powerful. I would recommend horking > around with some of the Apple provided examples to gain an > understanding of how PBX works and how projects are structured, etc... > > For Python files, go into the target inspector and click on the > "Bundle Resources" build phase. You should see the python files > listed in that section. If not, try drag-n-drop'ing the python files > into the list. That's it, nibwrapper.py was not in the list. I've added it manually and after rebuilding the latest version of PyObjC with /usr/bin/python TableModel2 worked correctly again. Thanks for the tip, Ronald |
From: Ronald O. <ous...@ci...> - 2002-10-31 21:42:33
|
On Thursday, Oct 31, 2002, at 14:20 Europe/Amsterdam, bb...@ma... wrote: > >> 2. If not, how could this be implemented? > > It is is implemented by: - The python sources are copied to the Resources directory of the application Do we have any control over this? I'd like to be able to convert the sources to bytecode (slightly faster startup, and this makes it harder to change the code). > > - using a series of copy file phases to copy the PyObjC module > into the 'pyobjc' subdirectory of the Resources directory of the > application when the 'install' target is used ('pbxbuild install' from > the command line). > > - the main.m uses execve() to transfer control to /usr/bin/python > and exec Main.py in a fashion where OS X thinks that /usr/bin/python > is the executable within the app wrapper (otherwise, mainBundle > breaks). Unfortunately, this is what breaks gdb. Fortunately, this > will go away when Apple ships a new build of Python that includes a > library for embedding. In a conversation about an 'addon-for-Apple-python' version of MacPython I mentioned this technique to Jack Jansen (the MacPython maintainer). He intends to use a slightly different technique: The wrapper does not use execve() /usr/bin/python, but a python binary(*) in the Contents/MacOS directory of the .app with and argv[0] that actually points to this python binary. The reason for this variation is that this would make 'sys.executable' point to a python interpreter and appearantly some existing code expects this (including the Python testsuite). We didn't know if the APIs that require a full path to the application in argv[0] would mind that argv[0] is not the name of the binary mentioned in the Info.plist. Ronald (*) Actually a symbolic link, but that is not important for the rest of this message. |
From: <bb...@ma...> - 2002-10-31 21:36:22
|
PBX is confusing, but amazingly powerful. I would recommend horking around with some of the Apple provided examples to gain an understanding of how PBX works and how projects are structured, etc... For Python files, go into the target inspector and click on the "Bundle Resources" build phase. You should see the python files listed in that section. If not, try drag-n-drop'ing the python files into the list. However, the should be listed by default because PBX doesn't know how to compile a python file... if not, something odd is going on. (See the WebServicesTool or TableModel2 as working examples) b.bum On Thursday, October 31, 2002, at 04:26 PM, Ronald Oussoren wrote: > Bill, > > I'm confused w.r.t. adding Python sources to a Project Builder > project. I've used the new 'mknibwrapper' tool in Example/TableModel2 > and can't seem to get a working version of the application: If added > the new python file using 'Project->Add Files...' and it shows up on > the correct location in the project. However it is not copied to the > output when I build the project. What am I doing wrong? > > A confused PB newbe, > Ronald |
From: Ronald O. <ous...@ci...> - 2002-10-31 21:26:55
|
Bill, I'm confused w.r.t. adding Python sources to a Project Builder project. I've used the new 'mknibwrapper' tool in Example/TableModel2 and can't seem to get a working version of the application: If added the new python file using 'Project->Add Files...' and it shows up on the correct location in the project. However it is not copied to the output when I build the project. What am I doing wrong? A confused PB newbe, Ronald |
From: Stephen S. <sst...@ma...> - 2002-10-31 17:54:00
|
> Thanks! Turns out I was confused about from whence I was getting my > python. /usr/local/bin contains the that I built from source and > that's the one into which I installed the pyobjc stuff. It works > fine...when I tell it to use that one. > > Thanks again! > > Steve > > On Thursday, October 31, 2002, at 12:06 AM, bb...@ma... wrote: > >> On Wednesday, October 30, 2002, at 11:38 PM, Stephen Steiner wrote: >>>> Or set the PythonBinPath user default to point to the python >>>> interpreter binary that you want to use [that has pyobjc installed >>>> within its site-packages]. >>> >>> Where would I find the 'PythonBinPath' user default (doc?)? >> >> It is mentioned in the bin-python-main.m file; it defaults to >> /usr/bin/python. As long as you can do the following, it should "just >> work" without setting that default. >> >> [bumbox:~] bbum% /usr/bin/python >> Python 2.2 (#1, 07/14/02, 23:25:09) >> [GCC Apple cpp-precomp 6.14] on darwin >> Type "help", "copyright", "credits" or "license" for more information. >> >>> from Foundation import * >> >>> x = NSMutableArray.array() >> >>> x >> () >> >>> >> >>> >>> When I run from within PB I get: >>> >>> [Switching to process 2631 thread 0xb03] >>> warning: ppc_frame_chain_valid: stack pointer from 0xbffffb1c to >>> 0x1000 grows upward; assuming invalid >> >> Because of the way the control is transferred to the python >> interpreter, you can't directly run the application under GDB. This >> limitation will go away once Apple ships a complete build of Python >> [the left out the ability to embed the interpreter into a binary and, >> as such, we have to execve() to pass control to the interpreter... >> this breaks gdb in the traditional sense]. See the mailing list >> archive if you want to run with gdb. >> >> Try just running the app from within PB -- not running it in the >> debugger. >> >> b.bum >> >> >> >> ------------------------------------------------------- >> This sf.net email is sponsored by: Influence the future of Java(TM) >> technology. Join the Java Community Process(SM) (JCP(SM)) program >> now. http://ads.sourceforge.net/cgi-bin/redirect.pl?sunm0004en >> _______________________________________________ >> Pyobjc-dev mailing list >> Pyo...@li... >> https://lists.sourceforge.net/lists/listinfo/pyobjc-dev >> >> > Steve > > Steve |
From: <bb...@ma...> - 2002-10-31 17:43:34
|
Excellent! I wish there was a cleaner way for us to handle this as it is definitely a source of confusion. b.bum On Thursday, October 31, 2002, at 12:25 PM, Stephen Steiner wrote: > Thanks! Turns out I was confused about from whence I was getting my > python. /usr/local/bin contains the that I built from source and > that's the one into which I installed the pyobjc stuff. It works > fine...when I tell it to use that one. |