Thread: [Pyobjc-dev] More on integer values
Brought to you by:
ronaldoussoren
From: David E. <epp...@ic...> - 2003-02-03 00:47:09
|
I just hit an error in my code; looks like the following scenario happened: 1. My code passed an integer value to undoManager.prepareWithInvocationTarget_ 2. I invoked an undo. 3. undoManager called my code with an NSCFInteger in place of the integer (so far, no problem...) 4. my code used that value as the column parameter of NSTableView.editColumn_row_withEvent_select_ 5. TypeError: expected an integer for argument 1: its typespec is 'i12' As usual, the workaround is to wrap the value in an int(), but shouldn't an objc integer be allowed to be used for this typespec? -- David Eppstein UC Irvine Dept. of Information & Computer Science epp...@ic... http://www.ics.uci.edu/~eppstein/ |
From: Bob I. <bo...@re...> - 2003-02-03 00:52:54
|
On Sunday, Feb 2, 2003, at 19:46 America/New_York, David Eppstein wrote: > I just hit an error in my code; looks like the following scenario > happened: > 1. My code passed an integer value to > undoManager.prepareWithInvocationTarget_ > 2. I invoked an undo. > 3. undoManager called my code with an NSCFInteger in place of the > integer > (so far, no problem...) > 4. my code used that value as the column parameter of > NSTableView.editColumn_row_withEvent_select_ > 5. TypeError: expected an integer for argument 1: its typespec is 'i12' > > As usual, the workaround is to wrap the value in an int(), but > shouldn't an objc integer be allowed to be used for this typespec? Well, from ObjC I would say no, if it expects an integer, it should get an int. int and NSNumber aren't interchangable on the ObjC side of things. -bob |
From: David E. <epp...@ic...> - 2003-02-03 02:08:29
|
On 2/2/03 7:52 PM -0500 Bob Ippolito <bo...@re...> wrote: > On Sunday, Feb 2, 2003, at 19:46 America/New_York, David Eppstein wrote: > >> I just hit an error in my code; looks like the following scenario >> happened: >> 1. My code passed an integer value to >> undoManager.prepareWithInvocationTarget_ >> 2. I invoked an undo. >> 3. undoManager called my code with an NSCFInteger in place of the >> integer >> (so far, no problem...) >> 4. my code used that value as the column parameter of >> NSTableView.editColumn_row_withEvent_select_ >> 5. TypeError: expected an integer for argument 1: its typespec is 'i12' >> >> As usual, the workaround is to wrap the value in an int(), but >> shouldn't an objc integer be allowed to be used for this typespec? > > Well, from ObjC I would say no, if it expects an integer, it should get > an int. int and NSNumber aren't interchangable on the ObjC side of > things. If they're not interchangeable, then maybe it's a bug that calling into and back from the undo manager is changing my ints into integers? The point is, I'm passing it arguments that should work, and it's giving me back ones that don't work. -- David Eppstein UC Irvine Dept. of Information & Computer Science epp...@ic... http://www.ics.uci.edu/~eppstein/ |
From: <bb...@ma...> - 2003-02-03 03:35:30
|
On Sunday, Feb 2, 2003, at 21:08 US/Eastern, David Eppstein wrote: > If they're not interchangeable, then maybe it's a bug that calling > into and back from the undo manager is changing my ints into integers? > The point is, I'm passing it arguments that should work, and it's > giving me back ones that don't work. The underlying problem is that the bridge has no way of knowing the signature of the method your are invoking upon prepareWithInvocationTarget_() and, as such, assumes everything passed into that method is an int. -prepareWithInvocationTarget_() basically configures the undo manager to act as a proxy for the next method call-- pushing that call onto a stack for later undo purposes. That is... >>> y = NSUndoManager.alloc().init() >>> y <NSUndoManager: 0x64bea0> >>> y.prepareWithInvocationTarget_(NSMutableArray.array()) <NSUndoManager: 0x64bea0> .... or, when used in context ... >>> a = NSMutableArray.array() >>> uM = NSUndoManager.alloc().init() >>> a.addObject_("foo") >>> uM.prepareWithInvocationTarget_(a).removeObject_("foo") >>> a (foo) >>> uM.undo() >>> a () ... the undo manager effectively captures the invocation of removeObject_() and stores it away until the undo() is invoked. At that point, undo() pops the captured invocation off the undo stack and invokes it. As far as the bridge can tell, removeObject_() is being invoked on the undo manager itself! As such, when the bridge tries to query the undo manager for the signature of the method being invoked, nothing is returned and the bridge falls back to sending across straight object representations of the various parameters. This causes a straight integer parameter to be converted to an (id) on the way to being captured by the undo manager. At least, I think it does. Fixing it may be hard. b.bum |
From: Ronald O. <ous...@ci...> - 2003-02-03 07:14:48
|
On Monday, Feb 3, 2003, at 04:35 Europe/Amsterdam, bb...@ma... wrote: > On Sunday, Feb 2, 2003, at 21:08 US/Eastern, David Eppstein wrote: >> If they're not interchangeable, then maybe it's a bug that calling >> into and back from the undo manager is changing my ints into >> integers? The point is, I'm passing it arguments that should work, >> and it's giving me back ones that don't work. > > The underlying problem is that the bridge has no way of knowing the > signature of the method your are invoking upon > prepareWithInvocationTarget_() and, as such, assumes everything passed > into that method is an int. is and object [ed.] ;-) [explanation of how NSUndoManager works removed for brevity] > At least, I think it does. Thats right. > > Fixing it may be hard. Not too hard. There are (at least) two possible solutions: - David could use objc.selector to specify a signature that is more to its liking (e.g. one of the arguments is an int instead of an object). I don't really like this, mostly because of the arcane interface of selector() - We could treat NSNumber like a Python number when translating arguments to Objective-C values. Doing that would not be too hard. Or we could translate NSNumbers to Python numbers when translating from Objective-C values to Python values, but I don't think we should do that. Ronald |
From: David E. <epp...@ic...> - 2003-02-03 07:59:16
|
On 2/3/03 8:13 AM +0100 Ronald Oussoren <ous...@ci...> wrote: > Not too hard. There are (at least) two possible solutions: > > - David could use objc.selector to specify a signature that is more to > its liking (e.g. one of the arguments is an int instead of an object). > I don't really like this, mostly because of the arcane interface of > selector() Rather than do that, I could (what I'm doing now) use int() to convert the type back to what I want. So this isn't an issue that's preventing me from getting anything done; it's more in the nature of a rough edge that it would be nice to smooth off before it confuses too many other people. -- David Eppstein UC Irvine Dept. of Information & Computer Science epp...@ic... http://www.ics.uci.edu/~eppstein/ |
From: Just v. R. <ju...@le...> - 2003-02-03 08:08:51
|
Ronald Oussoren wrote: > Or we could translate NSNumbers to Python numbers when translating > from Objective-C values to Python values, but I don't think we should > do that. Why not? It would surely be the least surprising behavior? Just |
From: <bb...@ma...> - 2003-02-03 15:02:51
|
On Monday, Feb 3, 2003, at 03:05 US/Eastern, Just van Rossum wrote: >> Or we could translate NSNumbers to Python numbers when translating >> from Objective-C values to Python values, but I don't think we should >> do that. > Why not? It would surely be the least surprising behavior? See my other message regarding David's problem. This would not solve the problem that David is having. Automatically converting NSNumbers to Python numbers and vice-versa is unnecessary and would lead to a major performance hit-- both CPU and memory-- in any many applications. In general, we do not want to autoconvert objects passing across the bridge unless it is unavoidable. Beyond the memory and CPU implications, it'll really hose any code that relies on the instance to the stay the same when passing across the bridge. If the goal is to make the bridge as transparent as possible, automatically converting instances-- and losing the original instance-- as they pass across the bridge should be eliminated. The fact that NSString<->PyString are converted is a bug -- certainly, a bug we have chosen to live with until a better solution comes along. Mostly, we can get away with this because two strings with the same contents act like the same string. For Python strings -> Objective-C, it is simply a matter of creating a subclass of the NSString class cluster in the same fashion as we do for NSArray and NSDictionary. For NSString -> Python StringType, it isn't clear that there is a set of methods or a base type to inherit from that can make an NSString behave like a python string transparently enough to make it a worthwhile pursuit at this point in time. Actually, for NSNumber there isn't any particular reason why a Python number type could not be encapsulated in an instance of a subclass of NSValue. It really doesn't buy us much since both sides of the bridge do a pretty good job of treating the instance of IntType or NSNumber that encapsulates a particular number as identical to another instance of the same class encapsulating the same number. b.bum |
From: Just v. R. <ju...@le...> - 2003-02-03 15:31:10
|
bb...@ma... wrote: > If the goal is to make the bridge as transparent as possible, > automatically converting instances-- and losing the original > instance-- as they pass across the bridge should be eliminated. If this is a refcount problem I can see that, but other than that, since Python numbers and NSNumber instances are immutable I don't see why it would ever matter to get a different instance. Wg. in Python it is an implementation detail that ints between -1 and 99 (as well as the empty tuple, empty string, strings of length 1) are singletons: one should never rely on that. To me, making "the bridge as transparent as possible" means the exact opposite: native Python objects on the Python side (strings, ints, floats, etc) and using native Cocoa objects on the ObjC side. I don't care about the performance hit, and I'm not even sure passing numbers back and forth over the bridge is such a common thing (but I'm sure you can prove otherwise ;-). > The fact that NSString<->PyString are converted is a bug -- To me it isn't, it's what I call "transparent". This feature is absolutely a _pleasure_ to work with. > certainly, a bug we have chosen to live with until a better solution > comes along. Mostly, we can get away with this because two strings > with the same contents act like the same string. Yeah, that's a neat property of them being immutable. I would figure the same goes for NSNumber, so apart from performance I don't see anything against converting back and forth. > For Python strings -> Objective-C, it is simply a matter of creating > a subclass of the NSString class cluster in the same fashion as we do > for NSArray and NSDictionary. For NSString -> Python StringType, > it isn't clear that there is a set of methods or a base type to > inherit from that can make an NSString behave like a python string > transparently enough to make it a worthwhile pursuit at this point in > time. It is clear: there is no such base class. In 2.3 there is an abstract base class called basestring but that doesn't implement anything. Just |
From: Bob I. <bo...@re...> - 2003-02-03 15:58:21
|
On Monday, Feb 3, 2003, at 10:30 America/New_York, Just van Rossum wrote: > bb...@ma... wrote: > >> The fact that NSString<->PyString are converted is a bug -- > > To me it isn't, it's what I call "transparent". This feature is > absolutely a _pleasure_ to work with. It's what I call a "real pain in the ass", at least when NSMutableString gets bridged into a PyString. Why can't we wrap the NSString class cluster with some cruft that makes it pythonic instead of converting it to something that it wasn't? There is absolutely no namespace clash between NSString and PyString, with the added bonus that NSString can do just about everything that PyString can with one line of code or less. -bob |
From: Ronald O. <ous...@ci...> - 2003-02-03 16:22:28
|
On Monday, Feb 3, 2003, at 16:58 Europe/Amsterdam, Bob Ippolito wrote: > > On Monday, Feb 3, 2003, at 10:30 America/New_York, Just van Rossum > wrote: > >> bb...@ma... wrote: >> >>> The fact that NSString<->PyString are converted is a bug -- >> >> To me it isn't, it's what I call "transparent". This feature is >> absolutely a _pleasure_ to work with. > > It's what I call a "real pain in the ass", at least when > NSMutableString gets bridged into a PyString. A real argument for not doing the conversion! Not converting can also be problematic: What if you pass the NSString to an extension-function that expects a string (like open), unless these get changed to also accept NSStrings you'll have to perform manual conversion from NSString to a python string. > > Why can't we wrap the NSString class cluster with some cruft that > makes it pythonic instead of converting it to something that it > wasn't? There is absolutely no namespace clash between NSString and > PyString, with the added bonus that NSString can do just about > everything that PyString can with one line of code or less. The 'problem' with NSString is that its interface is much more powerfull than that of python strings (the word cruft springs to mind when seeing methods like stringByAbbreviatingWithTildeInPath). In case anyone cares: I (still) haven't made made my mind up on whether automaticly converting values is a usefull feature or not. There are to many irritating 'features' on either solution (converting or wrapping). Ronald |
From: Just v. R. <ju...@le...> - 2003-02-03 16:45:55
|
[Bob Ippolito] > > It's what I call a "real pain in the ass", at least when > > NSMutableString gets bridged into a PyString. Now _that's_ a bug. There is no Python equivalent to NSMutableString, so it makes no sense to convert it. [Ronald Oussoren] > A real argument for not doing the conversion! Nope, an argument for not converting NSMutableString ;-) Just |
From: <bb...@ma...> - 2003-02-03 17:36:40
|
Unfortunately, it is not that simple; not that black/white. It is quite possible-- used to be common, but I'm seeing it less and less often-- for a method that is declared as.... - (NSString *) fooBar; ... to actually return an instance of NSMutableString. Contrary to initial belief, this is not a bug. NSString is a superclass of NSMutableString-- the declared return type tells the developer that they should treat the string as immutable and the developer must do so unless they either either want to put up with a bunch of compiler warnings or do an evil downcast for an object not their own. As such, we really can't limit conversion of strings to just the immutable strings while leaving the mutable strings alone. The end result would be vast amounts more confusion than we currently have -- there are situations where a method may return an NSString* instance some of the time and NSMutableString* instances at other times. However, I believe that *not* converting NSString and using a bridging mechanism similar as to what is used for NSArray and NSDictionary may work quite well. -- Python -> ObjC This is easy. Simply create a subclass of NSString that encapsulates an instance of a Python string [or character buffer] and implements the appropriate primitive methods. From there, it should "just work". No need to also provide a subclass of NSMutableString because Python strings are always immutable -- correct? -- ObjC -> Python A more difficult case because there isn't [yet] a <string> base type to inherit from that is used for all 'are you a string' testing. However, if one were to implement a Python module that providing a <character buffer> type API that wraps around an NSString [immutable only] instance, it appears that most of the Python core would handle that particular argument just fine. Example: the open() or file() functions would work just fine as long as the inbound object for the <name> argument is a character buffer (as that function-- open is just an alias for file anyway-- uses 'et' as the parse format for PyArgs_ParseTupleAndKeywords()). -- Furthermore, the (id) of an object-- the address contained in self-- is often used as a meaningful identifier. If a developer places an object into a container-- a dictionary or an array-- they expect to retrieve the exact same instance-- the same self pointer-- upon retrieving that object. In this context, that an object is an (int) and the first 100 ints are singletons is completely irrelevant. Consider the object in pure OO terms-- it is just an object contained in a collection, its type does not matter. In my experience with bridging-- many years and going between a number of different languages-- conversion always turns out to be a headache. Sometimes, there is more benefit from doing the conversion than there would be from not doing so, but that is *rarely* the case and there is *always* a price to be paid for doing the conversion. Do not discount the performance hit -- it can be truly nasty. In the context of the Java<->ObjC bridge, the fact that Strings<->NSStrings conversions occur means that bridged code using ObjC collections is so astoundingly slow and memory inefficient as to require the developer to often change the design patterns radically (at least, that *was* the case with the WO 4.5 / OS X PB and prior bridge -- don't know if it still is, but I imagine it likely is). In the case of Java, doing this kind of conversion is basically a requirement in that you can't subclass Java's String class and the kit of objects has no analogous structure such as Python's use of <character buffer>. b.bum On Monday, Feb 3, 2003, at 11:45 US/Eastern, Just van Rossum wrote: > [Bob Ippolito] >>> It's what I call a "real pain in the ass", at least when >>> NSMutableString gets bridged into a PyString. > > Now _that's_ a bug. There is no Python equivalent to NSMutableString, > so > it makes no sense to convert it. > > [Ronald Oussoren] >> A real argument for not doing the conversion! > > Nope, an argument for not converting NSMutableString ;-) |
From: Just v. R. <ju...@le...> - 2003-02-03 19:13:09
|
bb...@ma... wrote: > Unfortunately, it is not that simple; not that black/white. Is it ever? ;-) > It is quite possible-- used to be common, but I'm seeing it less and > less often-- for a method that is declared as.... > > - (NSString *) fooBar; > > .... to actually return an instance of NSMutableString. Contrary to > initial belief, this is not a bug. NSString is a superclass of > NSMutableString-- the declared return type tells the developer that > they should treat the string as immutable and the developer must do so > unless they either either want to put up with a bunch of compiler > warnings or do an evil downcast for an object not their own. I recently learned about this but hadn't thought of it in this context. I don't assume the _declared_ return type is available at runtime? If so, we could use that, but I guess it isn't. > As such, we really can't limit conversion of strings to just the > immutable strings while leaving the mutable strings alone. The end > result would be vast amounts more confusion than we currently have -- Where the value of "vast" depends on how frequently this pattern actually occurs in the call you use. > there are situations where a method may return an NSString* instance > some of the time and NSMutableString* instances at other times. > > However, I believe that *not* converting NSString and using a bridging > mechanism similar as to what is used for NSArray and NSDictionary may > work quite well. Hm, perhaps you're right. > -- > > Python -> ObjC > > This is easy. Simply create a subclass of NSString that > encapsulates an instance of a Python string [or character buffer] and > implements the appropriate primitive methods. From there, it should > "just work". No need to also provide a subclass of NSMutableString > because Python strings are always immutable -- correct? Correct. > -- > > ObjC -> Python > > A more difficult case because there isn't [yet] a <string> base type > to inherit from that is used for all 'are you a string' testing. > > However, if one were to implement a Python module that providing a > <character buffer> type API that wraps around an NSString [immutable > only] instance, it appears that most of the Python core would handle > that particular argument just fine. > > Example: the open() or file() functions would work just fine as > long as the inbound object for the <name> argument is a character > buffer (as that function-- open is just an alias for file anyway-- > uses 'et' as the parse format for PyArgs_ParseTupleAndKeywords()). But what about (say) regular expressions on unicode strings? > -- > > Furthermore, the (id) of an object-- the address contained in self-- > is often used as a meaningful identifier. If a developer places an > object into a container-- a dictionary or an array-- they expect to > retrieve the exact same instance-- the same self pointer-- upon > retrieving that object. Such an assumption is only safe if the code works directly with these collection objects. I don't think any code can be called sane it it stops working when it receives an object from elsewhere that has a different id than it expects. > In this context, that an object is an (int) and the first 100 ints are > singletons is completely irrelevant. Consider the object in pure OO > terms-- it is just an object contained in a collection, its type does > not matter. I don't see why the id should matter either. From a Python perspective, all that matters is that the two objects compare and hash equally. Sure, comparison is _cheaper_ when the two objects have the same id, but would stuff actually _break_ if the id's weren't the same? That's just sick. > In my experience with bridging-- many years and going between a > number of different languages-- (Do you have a macro for that sentence? ;-) > conversion always turns out to be a > headache. Sometimes, there is more benefit from doing the conversion > than there would be from not doing so, but that is *rarely* the case > and there is *always* a price to be paid for doing the conversion. > > Do not discount the performance hit -- it can be truly nasty. Yet Python is _primarily_ about convenience. Efficiency is secondary. Using Python comes at a price, and every bridge causes some overhead. For example passing a C string to Python *always* causes the string to be copied. I don't see what's so inherently bad at treating NSStrings the same way. Regarding numbers: from ObjC -> Python there will be hardly a difference between conversion and wrapping: for both cases a new object needs to be allocated (except when the number is between -1 and 99 in which case conversion is _cheaper_). It's _great_ that wrapped NSArrays work much like lists but aren't, and I wouldn't want it any other way, but a number should really be a number. > In the context of the Java<->ObjC bridge, the fact that > Strings<->NSStrings conversions occur means that bridged code using > ObjC collections is so astoundingly slow and memory inefficient as to > require the developer to often change the design patterns radically > (at least, that *was* the case with the WO 4.5 / OS X PB and prior > bridge -- don't know if it still is, but I imagine it likely is). I don't buy this: why use Foundation collections on a large scale in a _Python_ app? The situation where *both* Python and ObjC need to access a dict in tight loops sounds fairly unlikely. You can choose NSDictionary or dict depending on whether Python or ObjC will need to access it most frequently. Just |
From: Ronald O. <ous...@ci...> - 2003-02-04 06:57:47
|
On Monday, Feb 3, 2003, at 20:12 Europe/Amsterdam, Just van Rossum wrote: > > I recently learned about this but hadn't thought of it in this context. > I don't assume the _declared_ return type is available at runtime? If > so, we could use that, but I guess it isn't. The declared return and argument types aren't available beyond "it's an object". Most of these type declarations are only used for compile-time checks. >> -- >> >> Furthermore, the (id) of an object-- the address contained in self-- >> is often used as a meaningful identifier. If a developer places an >> object into a container-- a dictionary or an array-- they expect to >> retrieve the exact same instance-- the same self pointer-- upon >> retrieving that object. > > Such an assumption is only safe if the code works directly with these > collection objects. I don't think any code can be called sane it it > stops working when it receives an object from elsewhere that has a > different id than it expects. The assumption could lead to bugs for some types (like integers): There is no guarantee whatsever on the value of 'id(x+1) == id(x+1)' if x is an integer. That means that you might think you add two different objects to a list while you add only one (or v.v.!) > >> In this context, that an object is an (int) and the first 100 ints are >> singletons is completely irrelevant. Consider the object in pure OO >> terms-- it is just an object contained in a collection, its type does >> not matter. > > I don't see why the id should matter either. From a Python perspective, > all that matters is that the two objects compare and hash equally. > Sure, > comparison is _cheaper_ when the two objects have the same id, but > would > stuff actually _break_ if the id's weren't the same? That's just sick. Not necessarily, I'm sure we can come up with sane scenarios where object identity is used other than as a performance hack. That said: type *does* matter (see above). > > Yet Python is _primarily_ about convenience. Efficiency is secondary. > Using Python comes at a price, and every bridge causes some overhead. > For example passing a C string to Python *always* causes the string to > be copied. I don't see what's so inherently bad at treating NSStrings > the same way. > > Regarding numbers: from ObjC -> Python there will be hardly a > difference > between conversion and wrapping: for both cases a new object needs to > be > allocated (except when the number is between -1 and 99 in which case > conversion is _cheaper_). And likewise for Python->ObjC: A new object will be created. Ronald |
From: Just v. R. <ju...@le...> - 2003-02-04 09:01:59
|
Ronald Oussoren wrote: > > I don't see why the id should matter either. From a Python > > perspective, all that matters is that the two objects compare and > > hash equally. Sure, comparison is _cheaper_ when the two objects > > have the same id, but would stuff actually _break_ if the id's > > weren't the same? That's just sick. > > Not necessarily, I'm sure we can come up with sane scenarios where > object identity is used other than as a performance hack. Sure, eg. in Python this happens with exceptions. However we're not talking about arbitrary objects, but about real basic immutable types (strings and numbers). I claim that any code in which the id of an NSNumber or NSString is important is seriously broken. > > Regarding numbers: from ObjC -> Python there will be hardly a > > difference between conversion and wrapping: for both cases a new > > object needs to be allocated (except when the number is between -1 > > and 99 in which case conversion is _cheaper_). > And likewise for Python->ObjC: A new object will be created. Not for a wrapped NSNumber, when you would just pass the original object back. Just |
From: <bb...@ma...> - 2003-02-04 12:52:50
|
On Tuesday, Feb 4, 2003, at 04:01 US/Eastern, Just van Rossum wrote: > Sure, eg. in Python this happens with exceptions. However we're not > talking about arbitrary objects, but about real basic immutable types > (strings and numbers). I claim that any code in which the id of an > NSNumber or NSString is important is seriously broken. That claim is faulty. There are many situations where the type of the object is totally irrelevant to the local implementation. That is, as far as the implementation is concerned, everything is an (NSObject*) and the only important piece of information is the id-- the self pointer-- of that object. As Ronald indicated, this situation arises outside of various random performance hacks-- NSMapTables and the underlying CF* types are often used to map instances to other instances, regardless of type, as a part of object graph maintenance. By assuming otherwise, the bridge will cause very subtle, but very ugly, problems in many situations where the developer is going to be mighty surprised that it didn't "just work". We already have that situation with the string conversions that are happening now. b.bum |
From: Just v. R. <ju...@le...> - 2003-02-04 13:29:13
|
bb...@ma... wrote: > On Tuesday, Feb 4, 2003, at 04:01 US/Eastern, Just van Rossum wrote: > > Sure, eg. in Python this happens with exceptions. However we're not > > talking about arbitrary objects, but about real basic immutable > > types (strings and numbers). I claim that any code in which the id > > of an NSNumber or NSString is important is seriously broken. > > That claim is faulty. Uh, I didn't say such code didn't _exist_. > There are many situations where the type of the object is totally > irrelevant to the local implementation. That is, as far as the > implementation is concerned, everything is an (NSObject*) and the > only important piece of information is the id-- the self pointer-- of > that object. As Ronald indicated, this situation arises outside of > various random performance hacks-- NSMapTables and the underlying CF* > types are often used to map instances to other instances, regardless > of type, as a part of object graph maintenance. Can't find decent doco for NSMapTable, yet what I have found says it's not even a true object (it's not even an id); just an opaque struct with a functional interface. Where are the semantics of NSMapTable _visible_ when using Cocoa classes, and in what case would code actually break if we supply it with an NSNumber with a different id? I want things to be as convenient as possible in the usual case, I don't mind some odd surprises in extreme cases. NSMapTable seems sufficiently low level that I don't see how it can be relevant to Python code using Cocoa. > By assuming otherwise, the bridge will cause very subtle, but very > ugly, problems in many situations where the developer is going to be > mighty surprised that it didn't "just work". I don't believe your "many" qualifier here. A real example would be useful. > We already have that > situation with the string conversions that are happening now. Like where? (Apart from the NSMutableString conversion bug of course.) Just |
From: Bob I. <bo...@re...> - 2003-02-03 18:38:40
|
On Monday, Feb 3, 2003, at 11:21 America/New_York, Ronald Oussoren wrote: > > On Monday, Feb 3, 2003, at 16:58 Europe/Amsterdam, Bob Ippolito wrote: > >> >> On Monday, Feb 3, 2003, at 10:30 America/New_York, Just van Rossum >> wrote: >> >>> bb...@ma... wrote: >>> >>>> The fact that NSString<->PyString are converted is a bug -- >>> >>> To me it isn't, it's what I call "transparent". This feature is >>> absolutely a _pleasure_ to work with. >> >> It's what I call a "real pain in the ass", at least when >> NSMutableString gets bridged into a PyString. > A real argument for not doing the conversion! > > Not converting can also be problematic: What if you pass the NSString > to an extension-function that expects a string (like open), unless > these get changed to also accept NSStrings you'll have to perform > manual conversion from NSString to a python string. Say NSString acts like 100% like UserString (i.e. implements __str__ and such), wouldn't PyArg_ParseTuple(AndKeywords) do The Right Thing? >> >> Why can't we wrap the NSString class cluster with some cruft that >> makes it pythonic instead of converting it to something that it >> wasn't? There is absolutely no namespace clash between NSString and >> PyString, with the added bonus that NSString can do just about >> everything that PyString can with one line of code or less. > > The 'problem' with NSString is that its interface is much more > powerfull than that of python strings (the word cruft springs to mind > when seeing methods like stringByAbbreviatingWithTildeInPath). Well since there is no namespace clash, NSString doesn't lose those. If PyArg_ParseTuple does The Right Thing, this (useless code) should work: myDesktop = NSString('~/Desktop').stringByAbbreviatingWithTildeInPath() myHomedir, myDesktop = os.path.split(myDesktop) > > In case anyone cares: I (still) haven't made made my mind up on > whether automaticly converting values is a usefull feature or not. > There are to many irritating 'features' on either solution (converting > or wrapping). I'm really against converting NSMutableANYTHING. I can think of at least one AppKit class where you can get a NSMutableString (perhaps it's a subclass of) as an rval to some method, where you change that NSMutableString and the view changes its contents based upon any changes you make to that NSMutableString (without having to call any additional methods). -bob |
From: David E. <epp...@ic...> - 2003-02-03 19:15:09
|
Shouldn't the following work? I get an exception, str has no setString_ method... I was hoping to use NSMutableString for my testing of int undo handling, since it is simpler to set up than the NSTableView method where I ran across the int issue, but I guess I'll have to look for something else... # test ability to use NSMutableString from Foundation import NSObject, NSMutableString class TestUndoInt (NSObject): def init(self): self.string = NSMutableString.stringWithCapacity_(20) self.string.setString_("initial") x = TestUndoInt.alloc().init() assert(str(x.string) == 'initial') -- David Eppstein UC Irvine Dept. of Information & Computer Science epp...@ic... http://www.ics.uci.edu/~eppstein/ |
From: <bb...@ma...> - 2003-02-03 19:25:11
|
On Monday, Feb 3, 2003, at 14:15 US/Eastern, David Eppstein wrote: > Shouldn't the following work? I get an exception, str has no > setString_ method... I was hoping to use NSMutableString for my > testing of int undo handling, since it is simpler to set up than the > NSTableView method where I ran across the int issue, but I guess I'll > have to look for something else... > > ... test case deleted ... First, thank you for the test case. That particular behavior is expected (but maybe not correct-- your test case nicely summates what is currently being debated in the rest of this thread). The bridge automatically converts any instance of NSString going from ObjC->Python to a Python String. End result is this... self.string = NSMutableString.stringWithCapacity_(20) ... causes self.string to be a Python string [likely of length 0]. b.bum |
From: Just v. R. <ju...@le...> - 2003-02-03 19:19:58
|
Bob Ippolito wrote: > > Not converting can also be problematic: What if you pass the > > NSString to an extension-function that expects a string (like > > open), unless these get changed to also accept NSStrings you'll > > have to perform manual conversion from NSString to a python string. > > Say NSString acts like 100% like UserString (i.e. implements __str__ > and such), wouldn't PyArg_ParseTuple(AndKeywords) do The Right Thing? I have no idea how well this can work, but UserString seems to be a pain: Python 2.3a1 (#106, Feb 2 2003, 19:33:52) [GCC 3.1 20020420 (prerelease)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> import re >>> from UserString import UserString >>> s = UserString("lalalala") >>> s 'lalalala' >>> repr(s) "'lalalala'" >>> open(s) Traceback (most recent call last): File "<stdin>", line 1, in ? TypeError: coercing to Unicode: need string or buffer, instance found >>> re.match("la", s) Traceback (most recent call last): File "<stdin>", line 1, in ? File "/usr/local/lib/python2.3/sre.py", line 132, in match return _compile(pattern, flags).match(string) TypeError: expected string or buffer >>> Just |
From: Bob I. <bo...@re...> - 2003-02-03 20:10:49
|
On Monday, Feb 3, 2003, at 14:19 America/New_York, Just van Rossum wrote: > Bob Ippolito wrote: > >>> Not converting can also be problematic: What if you pass the >>> NSString to an extension-function that expects a string (like >>> open), unless these get changed to also accept NSStrings you'll >>> have to perform manual conversion from NSString to a python string. >> >> Say NSString acts like 100% like UserString (i.e. implements __str__ >> and such), wouldn't PyArg_ParseTuple(AndKeywords) do The Right Thing? > > I have no idea how well this can work, but UserString seems to be a > pain: Well, that sucks. I'd consider that a bug. With 2.2's unification of types and classes you SHOULD be able to do this. :( I guess after re-reading http://www.python.org/2.2/descrintro.html it comes down to the equivalent of: """ However, our __getitem__() method is not used for variable access by the interpreter: >>> exec "print foo" in a Traceback (most recent call last): File "<stdin>", line 1, in ? File "<string>", line 1, in ? NameError: name 'foo' is not defined >>> Why doesn't this print 0.0? The interpreter uses an internal function to access the dictionary, which bypasses our __getitem__() override. I admit that this can be a problem (although it is only a problem in this context, when a dict subclass is used as a locals/globals dictionary); it remains to be seen if I can fix this without compromising performance in the common case. """ I haven't looked at the internals of the bridge, but what about something like this (imagine B is NSString, and A is MyPyStringCruftForNSString) >>> class A(str): ... def __new__(clazz, myObject): ... s = str.__new__(clazz, repr(myObject)) ... s._obj = myObject ... return s ... def __getattr__(self, attr): ... return getattr(self._obj, attr) ... >>> class B(object): ... blah = 1 ... blahblah = 2 ... >>> a = A(B()) >>> a '<__main__.B object at 0x1673e0>' >>> a.blah 1 Unfortunately this _still_ won't work with re.match (at least in Jaguar's 2.2.0, I'd consider this a bug in re.match), but it *does* work with open() >>> class C(str): ... def length(self): ... return len(self) ... >>> c = C('lalala') >>> c.length() 6 >>> re.match('la', c) <_sre.SRE_Match object at 0x159750> >>> _.groups() () >>> re.match('moo', c) >>> re.match is obviously *finding* a match, but it's just not building the groups right. I'll file a bug on sourceforge. This is obviously not a solution for NSMutableString though, but it might make the bridge for static strings a little snazzier (maintain all original functionality).. you don't lose the NSString object, but you gain *just about* full PyString magic.. anything that breaks you can 'fix' with str(myInstance) -bob |
From: Just v. R. <ju...@le...> - 2003-02-03 20:18:45
|
Bob Ippolito wrote: > re.match is obviously *finding* a match, but it's just not building > the groups right. I'll file a bug on sourceforge. It bahaves the same with a regular string, though: >>> re.match("la", "lalala").groups() () I think the .groups() method only returns explicit groups, and not group(0). Just |
From: Bob I. <bo...@re...> - 2003-02-03 20:26:38
|
On Monday, Feb 3, 2003, at 15:18 America/New_York, Just van Rossum wrote: > Bob Ippolito wrote: > >> re.match is obviously *finding* a match, but it's just not building >> the groups right. I'll file a bug on sourceforge. > > It bahaves the same with a regular string, though: > >>>> re.match("la", "lalala").groups() > () > > I think the .groups() method only returns explicit groups, and not > group(0). My bad, you're right. I sure am full of mistakes today. It's obviously been far too long since I've used the re module; I think I've used re.match two or three times in the past year.. Kind of strange that when I was doing @P$e%r&l I'd use regular expressions all over the place, it's probably because PyString has enough features to make re unnecessary in most situations. -bob |