Re: [Python-Dev] PEP 246, redux
On 2005 Jan 11, at 11:01, Alex Martelli wrote: On 2005 Jan 10, at 18:59, Phillip J. Eby wrote: At 12:43 PM 1/10/05 -0500, Phillip J. Eby wrote: As a practical matter, all of the existing interface systems (Zope, PyProtocols, and even the defunct Twisted implementation) treat interface inheritance as guaranteeing substitutability for the base interface, and do so transitively. An additional data point, by the way: the Eclipse Java IDE has an adaptation system that works very much like PEP 246 does, and it appears that in a future release they intend to support automatic adapter transitivity, so as to avoid requiring each provider of an interface to provide O(n^2) adapters when writing the nth version of an interface. IOW, their current release is transitive only for interface inheritance ala Zope or Twisted; their future release will be transitive for adapter chains ala PyProtocols. This is definitely relevant prior art, so thanks for pointing it out. If interfaces change so often that 'n' can become worryingly high, this is a valid concern. In my world, though, published interfaces do NOT change as often as to require such remedies;-). ...that was a bit too flippant -- I apologize. It DOES happen that interfaces keep changing, and other situations where adapter-chain transitivity is quite handy do, absolutely!, occur, too. Reflecting on Microsoft's QI (QueryInterface), based on a very strong injunction against changing interfaces and yet mandating transitivity, points that out -- that's prior art, too, and a LOT more of it than Eclipse can accumulate any time soon, considering how long COM has been at the heart of Microsoft's components strategy, how many millions of programmers have used or abused it. Still, QI's set of constraints, amounting to a full-fledged equivalence relationship among all the adapters for a single underlying object, is, I fear, stronger than we can impose (so it may be that Eclipse is a better parallel, but I know little of it while COM is in my bones, so that's what I keep thinking of;-). So, I see transitivity as a nice thing to have _IF_ it's something that gets explicitly asserted for a certain adapter -- if the adapter has to explicitly state to the system that it isn't lossy (maybe), or isn't noisy (perhaps more useful), or something like that... some amount of reassurance about the adapter that makes it fully safe to use in such a chain. Maybe it might suffice to let an adapter which IS 'lossy' (or, more likely, one that is 'noisy') state the fact. I'm always reluctant by instinct to default to convenient but risky behavior, trusting programmers to explicitly assert otherwise when needed; but in many ways this kind of design is a part of Python and works fine (_with_ the BDFL's fine nose/instinct for making the right compromise between convenience and safety in each case, of course). I'm still pondering the don't adapt an adapter suggestion, which seems a sound one, and yet also seems to be, intrinsically, what transitivity-by-chaining does. Note that QI does not suffer from this, because it lets you get the underlying object identity (IUnknown) from any interface adapter. Maybe, just maybe, we should also consider that -- a distinguished protocol bereft of any real substance but acting as a flag for real unadapted object identity. Perhaps we could use 'object' for that, at least if the flow of logic in 'adapt' stays as in the current PEP 246 draft (i.e., __conform__ is given a chance before isinstance triggers -- so, all adapters could __conform__ to object by returning the underlying object being adapted, while other objects without such a feature in __conform__ would end up with 'adapt(x, object) is x'). Or, if object in this role turns out to be confusing, IDentity (;-) or some other specially designed protocol. If we had this ability to get at the underlying object we could at least write clearer axioms about what transitivity must mean, as well as, help out with the adapting an adapter problems. E.g., imagine: def f(x: IFoo, y: IFoo): if x is y: ... that wouldn't work if adapt(x, IFoo) returns a separate adapter each time, which is the most likely situation (think, again, of str-file adaptation by StringIO wrapping); but recovering underlying identities by adapt(x, object) is adapt(y, object) would work. I don't think that IUnknown or an equivalent, per se, can do *instead* of the need to have an adapter explicitly state it's non-noisy (or VV). Besides the need to check for object identity, which is pretty rare except when writing axioms, invariants or pre/post-conds;-), the IUnknown equivalent would perhaps be more of a conceptual/philosophical 'prop' than a practically useful feature -- while I see the ability to block unintended consequences of inheritance and transitivity (or even better, state explicitly when those consequences are wanted, even if that should be 90% of the
Re: [Python-Dev] PEP 246, redux
On 2005 Jan 11, at 16:34, Phillip J. Eby wrote: ... Anyway, I agree that your version of the code should be used to form the reference implementation, since the purpose of the reference implementation is to show the complete required semantics. Great, one point at last on which we fully agree -- thanks Armin!-) I was waiting for BDFL feedback before editing the PEP again, but if none is forthcoming I guess at some point I'll go ahead and at least to the edits that are apparently not controversial, like this one. I'd like to have a summary of controversial points and short pro and con args, too, but I'm not unbiased enough to write it all by myself...;-) Alex ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] PEP 246, redux
Phillip: I think you must inhabit a far more perfect world than I do. You say, for instance, that: ...-1 if this introduces a performance penalty [...] just to support people who want to create deliberate Liskov violations. I personally don't think that we should pander to Liskov violators ... but in my world, people violate Liskov all the time, even in languages that attempt (unsuccessfully) to enforce it. [1] You say that: I think one should adapt primarily to interfaces, and interface-to-interface adaptation should be reserved for non-lossy, non-noisy adapters. ... but in my world, half the time I'm using adaptation to correct for the fact that someone else's poorly-written code requests some class where it should have just used an interface. You seem to inhabit a world in which transitivity of adaptation can be enforced. But in my world, people occasionally misuse adaptation because they think they know what they're doing or because they're in a big hurry and it's the most convenient tool at hand. I wish I lived in your world, but I don't. -- Michael Chermside [1] - Except for Eiffel. Eiffel seems to do a pretty good job of enforcing it. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] logging class submission
Title: RE: [Python-Dev] logging class submission [Stephan Stapel] #- There's a license issue here? #- #- I was given the advise to use this license. If this license #- prohibts inclusion into Python, how should I re-license the code? I just was asking. Who gave you the advise? . Facundo Bitácora De Vuelo: http://www.taniquetil.com.ar/plog PyAr - Python Argentina: http://pyar.decode.com.ar/ . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . ADVERTENCIA. La información contenida en este mensaje y cualquier archivo anexo al mismo, son para uso exclusivo del destinatario y pueden contener información confidencial o propietaria, cuya divulgación es sancionada por la ley. Si Ud. No es uno de los destinatarios consignados o la persona responsable de hacer llegar este mensaje a los destinatarios consignados, no está autorizado a divulgar, copiar, distribuir o retener información (o parte de ella) contenida en este mensaje. Por favor notifíquenos respondiendo al remitente, borre el mensaje original y borre las copias (impresas o grabadas en cualquier medio magnético) que pueda haber realizado del mismo. Todas las opiniones contenidas en este mail son propias del autor del mensaje y no necesariamente coinciden con las de Telefónica Comunicaciones Personales S.A. o alguna empresa asociada. Los mensajes electrónicos pueden ser alterados, motivo por el cual Telefónica Comunicaciones Personales S.A. no aceptará ninguna obligación cualquiera sea el resultante de este mensaje. Muchas Gracias. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] logging class submission
On Tue, 2005-01-11 at 12:58, Batista, Facundo wrote: [Stephan Stapel] #- There's a license issue here? #- #- I was given the advise to use this license. If this license #- prohibts inclusion into Python, how should I re-license the code? I just was asking. Who gave you the advise? Here's a link to the PSF contribution form: http://www.python.org/psf/contrib.html This contains links to the recommended licenses for software that might be included in Python. -Barry signature.asc Description: This is a digitally signed message part ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] logging class submission
I just was asking. Who gave you the advise? someon in a german python forum. I'll change the license asap. I'm just curious, but do I really have to use the contributor agreement etc.? I mean I'm just trying to submit a small class, no big framework. cheers, Stephan Verschicken Sie romantische, coole und witzige Bilder per SMS! Jetzt neu bei WEB.DE FreeMail: http://freemail.web.de/?mc=021193 ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] PEP 246, redux
At 09:27 AM 1/11/05 -0800, Michael Chermside wrote: Phillip: I think you must inhabit a far more perfect world than I do. You say, for instance, that: ...-1 if this introduces a performance penalty [...] just to support people who want to create deliberate Liskov violations. I personally don't think that we should pander to Liskov violators I've since dropped both the performance objection and the objection to supporting Liskov violation; in a more recent post I've proposed an alternative algorithm for allowing it, that has a simpler implementation. You say that: I think one should adapt primarily to interfaces, and interface-to-interface adaptation should be reserved for non-lossy, non-noisy adapters. ... but in my world, half the time I'm using adaptation to correct for the fact that someone else's poorly-written code requests some class where it should have just used an interface. PEP 246 adaptation? Or are you talking about some other language? (I ask out of curiosity.) I agree that if it's possible to adapt to concrete types, people will do so. However, I think we all agree that this isn't a great idea and should still be considered bad style. That's not the same thing as saying it should be forbidden, and I haven't said it should be forbidden. You seem to inhabit a world in which transitivity of adaptation can be enforced. But in my world, people occasionally misuse adaptation because they think they know what they're doing or because they're in a big hurry and it's the most convenient tool at hand. How is this different from abuse of *any* language feature that you're then forced to work around? Are you saying we should not provide a feature because *some* people will abuse the feature? I don't understand. If you allow interface inheritance, you're just as susceptible to an invalid adaptation path, and in my experience this is more likely to bite you unintentionally, mainly because interface inheritance works differently than class inheritance (which of course is used more often). Do you want to prohibit interface inheritance, too? ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
On Tue, Jan 11, 2005 at 12:54:36PM -0500, Phillip J. Eby wrote: | * Replacing LiskovViolation is possible by dropping type/isinstance | checks from adapt(), and adding an isinstance check to | object.__conform__; Liskov violators then override __conform__ in their | class to return None when asked to conform to a protocol they wish to | reject, and return super().__conform__ for all other cases. This | achieves your use case while simplifying both the implementation and the | usage. I'd rather not assume that class inheritance implies substitutability, unless the class is marked as an interface (assuming that one doesn't have interfaces). I'd like it to be explicit -- a bit of a nudge to remind a developer to verify substitutability is a good thing. In this scenerio, a LiskovViolation exception isn't needed (aside, I don't see the rationale for the exception: to prevent third party adapters?). Could we make a boilerplate __conform__ which enables class-based substitutability a well-known decorator? | * In my experience, incorrectly deriving an interface from another is the | most common source of unintended adaptation side-effects, not adapter | composition It'd be nice if interfaces had a way to specify a test-suite that could be run against a component which claims to be compliant. For example, it could provide invalid inputs and assert that the proper errors are returned, etc. Best, Clark -- Clark C. Evans Prometheus Research, LLC. http://www.prometheusresearch.com/ o office: +1.203.777.2550 ~/ , mobile: +1.203.444.0557 // (( Prometheus Research: Transforming Data Into Knowledge \\ , \/- Research Exchange Database /\- Survey Assessment Technologies ` \ - Software Tools for Researchers ~ * ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
David Ascher writes: Terminology point: I know that LiskovViolation is technically correct, but I'd really prefer it if exception names (which are sometimes all users get to see) were more informative for people w/o deep technical background. Would that be possible? I don't see how. Googling on Liskov immediately brings up clear and understandable descriptions of the principle that's being violated. I can't imagine summarizing the issue more concisely than that! What would you suggest? Including better explanations in the documentation is a must, but LiskovViolation in the exception name seems unbeatably clear and concise. -- Michael Chermside ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
At 01:50 PM 1/11/05 -0500, Clark C. Evans wrote: On Tue, Jan 11, 2005 at 12:54:36PM -0500, Phillip J. Eby wrote: | * Replacing LiskovViolation is possible by dropping type/isinstance | checks from adapt(), and adding an isinstance check to | object.__conform__; Liskov violators then override __conform__ in their | class to return None when asked to conform to a protocol they wish to | reject, and return super().__conform__ for all other cases. This | achieves your use case while simplifying both the implementation and the | usage. I'd rather not assume that class inheritance implies substitutability, Hm, you should take that up with Alex then, since that is what his current PEP 246 draft does. :) Actually, the earlier drafts did that too, so I'm not sure why you want to change this now. What I've actually suggested here actually allows for inheritance=substitutability as the default, but also makes it trivially changeable for any given inheritance hierarchy by overriding __conform__ at the base of that hierarchy, and without introducing a special exception class to do it. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
At 09:23 PM 1/11/05 +0100, Alex Martelli wrote: Is the concept of *PRAGMATICS* so deucedly HARD for all of your eggheads?! Hmm. Pot, meet kettle. :) Yes, you're ALLOWED to stuff with NULL any field that isn't explicitly specified as NOT NULL. But you should ONLY do so when the information is REALLY missing, NOT when you've lost it along the way because you've implemented adapter-chain transitivity: dropping information which you COULD have preserved with a bit more care (==without transitivity) is a violation of PRAGMATICS, of the BEST-EFFORT implication, just as it would be to drop packets once in a while in a TCP/IP stack due to some silly programming bug which was passed silently. This is again a misleading analogy. You are comparing end-to-end with point-to-point. I am saying that if you have a point-to-point connection that drops all packets of a particular kind, you should not put it into your network, unless you know that an alternate route exists that can ensure those packets get through. Otherwise, you are breaking the network. Thus, I am saying that PRAGMATICALLY, it is silly to create a cable that drops all ACK packets, for example, and then plug it into your network. And especially, it's silly to turn around that as a reason that one should only use end-to-end leased lines, because that packet forwarding business is dangerously unreliable! As far as I can tell, you are arguing that you should never use packet forwarding for communication, because somebody might have a router somewhere that drops packets. While I am arguing that if a router is known to drop packets incorrectly, the router is broken and should be removed from the network, or else bypassed via another route. And, in the cases where you have a leased line direct from point A to point B, your routers should be smart enough to use that route in place of forwarding from A to C to D to B, or whatever. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] copy confusion
On 2005 Jan 11, at 23:20, Fredrik Lundh wrote: back in Python 2.1 (and before), an object could define how copy.copy should work simply by definining a __copy__ method. here's the relevant portion: ... try: copierfunction = _copy_dispatch[type(x)] except KeyError: try: copier = x.__copy__ except AttributeError: raise error, \ un(shallow)copyable object of type %s % type(x) y = copier() ... I recently discovered that this feature has disappeared in 2.3 and 2.4. in- stead of looking for an instance method, the code now looks at the object's type: Hmmm, yes, we were discussing this general issue as part of the huge recent thread about pep 246. In the new-style object model, special methods are supposed to be looked up on the type, not on the object; otherwise, having a class with special methods would be a problem -- are the methods meant to apply to the class object itself, or to its instances? However, apparently, the code you quote is doing it wrong: cls = type(x) copier = _copy_dispatch.get(cls) if copier: return copier(x) copier = getattr(cls, __copy__, None) if copier: return copier(x) ...because getattr is apparently the wrong way to go about it (e.g., it could get the '__copy__' from type(cls), which would be mistaken). Please see Armin Rigo's only recent post to Python-Dev for the way it should apparently be done instead -- assuming Armin is right (he generally is), there should be plenty of bugs in copy.py (ones that emerge when you're using custom metaclasses c -- are you doing that?). Still, if you're using an instance of an old-style class, the lookup in _copy_dispatch should be on types.InstanceType -- is that what you're trying to copy, an instance of an old-style class? (copy.deepcopy still seems to be able to use __deepcopy__ hooks, though) It starts with a peek into a dispatch dictionary for the type of the object, too, just like shallow copy does. What's the type of what you're trying to copy? is this a bug, or a feature of the revised copy/pickle design? (the code in copy_reg/copy/pickle might be among the more convoluted pieces of python coding that I ever seen... and what's that smiley doing in copy.py?) and if it's a bug, does the fact that nobody reported this for 2.3 indicate that I'm the only one using this feature? is there a better way to control copying that I should use instead? When I can, I use __getstate__ and __setstate__, simply because they seem clear and flexible to be (usable for copying, deep copying, pickling). But that doesn't mean __copy__ or __deepcopy__ should be left broken, of course. Although there are features of design intent here, it does appear to me there may be bugs too (if the getattr on the type is wrong); in this case it's worrisome, not just that nobody else reported problems, but also that the unit tests didn't catch them...:-( Alex ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: PEP 246: LiskovViolation as a name
My point is that it'd be nice if we could come up with an exception name which could be grokkable without requiring 1) Google, 2) relatively high-level understanding of type theory. How about SubstitutabilityError? The point is broader, though -- when I get my turn in the time machine, I'll lobby for replacing NameError with UndefinedVariable or something similar (or more useful still). The former is confusing to novices, and while it can be learned, that's yet another bit of learning which is, IMO, unnecessary, even though it may be technically more correct. We did that for UnboundLocalError, which subclasses NameError. Perhaps we can rename NameError to UnboundVariableError (and add NameError as an alias for b/w compat). -- --Guido van Rossum (home page: http://www.python.org/~guido/) ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] copy confusion
At 11:56 PM 1/11/05 +0100, Alex Martelli wrote: What both issues? There's only one issue, it seems to me -- one of metaconfusion. I was relying on Fredrik's report of a problem with the code; that is the other issue I referred to. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
On 2005 Jan 11, at 22:08, Phillip J. Eby wrote: ... Yes, you're ALLOWED to stuff with NULL any field that isn't explicitly specified as NOT NULL. But you should ONLY do so when the information is REALLY missing, NOT when you've lost it along the way because you've implemented adapter-chain transitivity: dropping information which you COULD have preserved with a bit more care (==without transitivity) is a violation of PRAGMATICS, of the BEST-EFFORT implication, just as it would be to drop packets once in a while in a TCP/IP stack due to some silly programming bug which was passed silently. This is again a misleading analogy. You are comparing end-to-end with point-to-point. I am saying that if you have a point-to-point connection that drops all packets of a particular kind, you should not put it into your network, unless you know that an alternate route exists that can ensure those packets get through. Otherwise, you are breaking the network. But adaptation is not transmission! It's PERFECTLY acceptable for an adapter to facade: to show LESS information in the adapted object than was in the original. It's PERFECTLY acceptable for an adapter to say this piece information is not known when it's adapting an object for which that information, indeed, is not known. It's only CONJOINING the two perfectly acceptable adapters, as transitivity by adapter chain would do automatically, that you end up with a situation that is pragmatically undesirable: asserting that some piece of information is not known, when the information IS indeed available -- just not by the route automatically taken by the transitivity-system. What happened here is not that either of the adapters registered is wrong: each does its job in the best way it can. The programming error, which transitivity hides (degrading the quality of information resulting from the system -- a subtle kind of degradation that will be VERY hard to unearth), is simply that the programmer forgot to register the direct adapter. Without transitivity, the programmer's mistake emerges easily and immediately; transitivity hides the mistake. By imposing transitivity, you're essentially asserting that, if a programmer forgets to code and register an A - C direct adapter, this is never a problem, as long as A - B and B - C adapters are registered, because A - B - C will give results just as good as the direct A - C would have, so there's absolutely no reason to trouble the programmer about the trivial detail that transitivity is being used. At the same time, if I understand correctly, you're ALSO saying that if two other adapters exist, A - Z and Z - C, *THEN* it's an error, because you don't know when adapting A - C whether to go via B or via Z. Well, if you consistently believe what I state in the previous paragraph, then this is just weird: since you're implicitly asserting that any old A-?-C transitive adaptation is just as good as a direct A-C, why should you worry about there being more than one such 2-step adaptation available? Roll the dice to pick one and just proceed. Please note that in the last paragraph I'm mostly trying to reason by absurd: I do NOT believe one can sensibly assert in the general case that A-?-C is just as good as A-C, without imposing FAR stronger constraints on adaptation that we possibly can (QI gets away with it because, designed from scratch, it can and does impose such constraints, essentially that all interfaces belong to ONE single object -- no independent 3rd party adaptation, which may be a bigger loss than the constraints gain, actually). I'm willing to compromise to the extent of letting any given adaptation somehow STATE, EXPLICITLY, this adaptation is lossless and perfect, and can be used as a part of transitive chains of adaptation without any cost whatsoever. If we do that, though, the adaptation system should trust this assertion, so if there are two possibilities of equal minimal length, such as A-B-C or A-Z-C, with all the steps being declared lossless and perfect, then it SHOULD just pick one by whatever criterion, since both will be equally perfect anyway -- so maybe my reasoning by absurd wasn't totally absurd after all;-). Would this compromise be acceptable to you? Alex ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
On Tue, Jan 11, 2005 at 03:30:19PM -0500, Phillip J. Eby wrote: | Clark said he didn't want to assume substitutability; I was pointing out | that he could choose to not assume that, if he wished, by implementing an | appropriate __conform__ at the base of his hierarchy. Oh, that's sufficient. If someone making a base class wants to assert that derived classes should check compliance (rather than having it automagic), then they can do this. Good enough! | I don't agree with Clark's use case, but my | proposal supports it as a possibility, and yours does not. It was a straw-man; and I admit, not a particularly compelling one. | To implement a Liskov violation with my proposal, you do exactly the same | as with your proposal, *except* that you can simply return None instead | of raising an exception, and the logic for adapt() is more | straightforward. I think I prefer just returning None rather than raising a specific exception. The semantics are different: None implies that other adaptation mechanisms (like a registry) could be tried, while LiskovException implies that processing halts and no further adaptation techniques are to be used. In this case, None is the better choice for this particular case since it would enable third-parties to register a wrapper. Overall, I think both you and Alex are now proposing essentially the same thing... no? Best, Clark -- Clark C. Evans Prometheus Research, LLC. http://www.prometheusresearch.com/ o office: +1.203.777.2550 ~/ , mobile: +1.203.444.0557 // (( Prometheus Research: Transforming Data Into Knowledge \\ , \/- Research Exchange Database /\- Survey Assessment Technologies ` \ - Software Tools for Researchers ~ * ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] copy confusion
At 02:58 PM 1/11/05 -0800, Guido van Rossum wrote: [Phillip] Looks like a bug to me; it breaks the behavior of classic classes, since type(classicInstance) returns InstanceType. I'm not so sure. I can't seem to break this for classic classes. Sorry; I was extrapolating from what I thought was Fredrik's description of this behavior as a bug, and examining of the history of the code that he referenced. I saw that the current version of that code had evolved directly from a version that was retrieving instance.__copy__; I therefore assumed that the loss-of-feature Fredrik was reporting was that. That is, I thought that the problem he was experiencing was that classic classes no longer supported __copy__ because this code had changed. I guess I should have looked at other lines of code besides the ones he pointed out; sorry about that. :( The only thing this intends to break, and then only for new-style classes, is the ability to have __copy__ be an instance variable (whose value should be a callable without arguments) -- it must be a method on the class. This is the same thing that I've done for all built-in operations (__add__, __getitem__ etc.). Presumably, this is the actual feature loss that Fredrik's describing; i.e. lack of per-instance __copy__ on new-style classes. That would make more sense. However, it also looks like it might have been introduced to fix the possibility that calling '__copy__' on a new-style class with a custom metaclass would result in ending up with an unbound method. (Similar to the metaconfusion issue being recently discussed for PEP 246.) Sorry, my head just exploded. :-( The issue is that for special attributes (like __copy__, __conform__, etc.) that do not have a corresponding type slot, using getattr() is not sufficient to obtain slot-like behavior. This is because 'aType.__special__' may refer to a __special__ intended for *instances* of 'aType', instead of the __special__ for aType. As Armin points out, the only way to fully emulate type slot behavior for unslotted special attributes is to perform a search of the __dict__ of each type in the MRO of the type of the object for which you wish to obtain the special attribute. So, in this specific case, __copy__ does not have a type slot, so it is impossible using getattr (or simple attribute access) to guarantee that you are retrieving the correct version of __copy__ in the presence of metaclasses. This is what Alex and I dubbed metaconfusion in discussion of the same issue for PEP 246's __adapt__ and __conform__ methods; until they have tp_adapt and tp_conform slots, they can have this same problem. Alex and I also just speculated that perhaps the stdlib should include a function that can do this, so that stdlib modules that define unslotted special attributes (such as __copy__) can ensure they work correctly in the presence of metaclasses. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] PEP 246, redux
At 06:38 PM 1/11/05 -0500, Clark C. Evans wrote: | To implement a Liskov violation with my proposal, you do exactly the same | as with your proposal, *except* that you can simply return None instead | of raising an exception, and the logic for adapt() is more | straightforward. I think I prefer just returning None rather than raising a specific exception. The semantics are different: None implies that other adaptation mechanisms (like a registry) could be tried, while LiskovException implies that processing halts and no further adaptation techniques are to be used. In this case, None is the better choice for this particular case since it would enable third-parties to register a wrapper. Overall, I think both you and Alex are now proposing essentially the same thing... no? Yes; I'm just proposing shuffling the invocation of things around a bit in order to avoid the need for an exception, and in the process increasing the number of possible customizations a bit. Not that I care about those customizations as such; I just would like to simplify the protocol. I suppose there's some educational benefit in making somebody explicitly declare that they're a Liskov violator, but it seems that if we're going to support it, it should be simple. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] copy confusion
back in Python 2.1 (and before), an object could define how copy.copy should work simply by definining a __copy__ method. here's the relevant portion: ... try: copierfunction = _copy_dispatch[type(x)] except KeyError: try: copier = x.__copy__ except AttributeError: raise error, \ un(shallow)copyable object of type %s % type(x) y = copier() ... I recently discovered that this feature has disappeared in 2.3 and 2.4. in- stead of looking for an instance method, the code now looks at the object's type: ... cls = type(x) copier = _copy_dispatch.get(cls) if copier: return copier(x) copier = getattr(cls, __copy__, None) if copier: return copier(x) ... (copy.deepcopy still seems to be able to use __deepcopy__ hooks, though) is this a bug, or a feature of the revised copy/pickle design? (the code in copy_reg/copy/pickle might be among the more convoluted pieces of python coding that I ever seen... and what's that smiley doing in copy.py?) and if it's a bug, does the fact that nobody reported this for 2.3 indicate that I'm the only one using this feature? is there a better way to control copying that I should use instead? /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] Re: copy confusion
Guido van Rossum wrote: The only thing this intends to break /.../ it breaks classic C types: import cElementTree x = cElementTree.Element(tag) x Element 'tag' at 00B4BA30 x.__copy__ built-in method __copy__ of Element object at 0x00B4BA30 x.__copy__() Element 'tag' at 00B4BA68 import copy y = copy.copy(x) Traceback (most recent call last): File stdin, line 1, in ? File C:\python24\lib\copy.py, line 93, in copy raise Error(un(shallow)copyable object of type %s % cls) copy.Error: un(shallow)copyable object of type type 'Element' dir(x) ['__copy__', '__deepcopy__', 'append', 'clear', 'find', 'findall', 'findtext', 'get', 'getchildren', 'getiterator', 'insert', 'items', 'keys', 'makeelement', 'set'] dir(type(x)) ['__class__', '__delattr__', '__delitem__', '__delslice__', '__doc__', '__getattribute__', '__getitem__', '__getslice__', '__hash__', '__init__', '__len__', '__new__', '__reduce__', '__reduce_ex__', '__repr__', '__setattr__', '__setitem__', '__setslice__', '__str__'] (and of course, custom C types is the only case where I've ever used __copy__; the default behavior has worked just fine for all other cases) for cElementTree, I've worked around this with an ugly __reduce__ hack, but that doesn't feel right... /F ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] PEP 246, redux
Thus, my argument is that an adapter like this should never be made part of the adapter system, even if there's no transitivity. However, if you agree that such an adapter shouldn't be implicit, then it logically follows that there is no problem with allowing transitivity, except of course that people may sometimes break the rule. At some point, the PEP should be extended to include a list of best practices and anti-patterns for using adapters. I don't find issues of transitivity and implicit conversion to be immediately obvious. Also, it is not clear to me how or if existing manual adaption practices should change. For example, if I need a file-like interface to a string, I currently wrap it with StringIO. How will that change it the future? By an explicit adapt/conform pair? Or by strings knowing how to conform to file-like requests? Raymond Hettinger ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
Re: [Python-Dev] Re: [Csv] csv module TODO list
Would the csv module be a good place to add a DBF reader and writer? I would have thought it would make sense as it's own module (in the same way that we have separate modules that present a common interface for the different databases), or am I missing something? I'd certainly like to see a DBF parser in python - reading and writing odd file formats is bread-and-butter for us contractors... 8-) -- Andrew McNamara, Senior Developer, Object Craft http://www.object-craft.com.au/ ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
[Python-Dev] PEP 246, redux
I'm trying to understand the relation between Guido's posts on optional static typing and PEP 245 (interfaces) and 246 (adaptation). I have a couple of questions PEP 245 proposes to introduce a fundamental distinction between type and interface. However, 245 only introduces a syntax for interfaces, and says very little about the semantics of interfaces. (Basically only that if X implements Y then implements(X, Y) will return True). The semantics of interfaces are currently only implied by PEP 246, and by Guido's posts referring to 246. Unfortunately PEP 246 explicitly refuses to decide that protocols are 245-style interfaces. Therefore, it is not clear to me how acceptance of 245 would impact on 246? Specifically, what would be the difference between: x = adapt(obj, a_245_style_interface) x = adapt(obj, a_protocol_type) and, if there is no difference, what would the use-case of interfaces be? Put another way: explicit interfaces and adaptation based typing seem to be about introducing rigor (dynamic, not static) to Python. Yet, PEP 245 and 246 seems to go out of their way to give interfaces and adaptation as little baggage as possible. So, where is the rigor going to come from? On the one hand this seems very Pythonic - introduce a new feature with as little baggage as possible, and see where it evolves from there. Let the rigor flow, not from the restrictions of the language, but from the expressive power of the language. On the other hand: why not, at least: - explore in 245 how the semantics of interfaces might introduce rigor into the language. It would be particularly illuminating to find out in what way implementing an interface differs from deriving from an ABC and in what way an interface hierarchy differs semantically from a hierarchy of ABCs - rewrite 246 under the assumption that 245 (including semantics) has been accepted I would volunteer, but, for those of you who hadn't noticed yet, I don't know what I'm talking about. Cheers, Roeland Rengelink ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com
RE: [Python-Dev] PEP 246, redux
At 07:52 PM 1/11/05 -0500, Raymond Hettinger wrote: Also, it is not clear to me how or if existing manual adaption practices should change. For example, if I need a file-like interface to a string, I currently wrap it with StringIO. How will that change it the future? By an explicit adapt/conform pair? Or by strings knowing how to conform to file-like requests? The goal here is to be able to specify that a function parameter takes, e.g. a readable stream, and that you should be able to either explicitly wrap in a StringIO to satisfy this, or *possibly* that you be able to just pass a string and have it work automatically. If the latter is the case, there are a variety of possible ways it might work. str.__conform__ might recognize the readable stream interface, or the __adapt__ method of the readable stream interface could recognize 'str'. Or, Alex's new proposed global type registry might contain an entry for 'str,readableStream'. Which of these is the preferred scenario very much depends on a lot of things, like who defined the readable stream interface, and whether anybody has registered an adapter for it! PyProtocols tries to answer this question by allowing you to register adapters with interfaces, and then the interface's __adapt__ method will do the actual adaptation. Zope does something similar, at least in that it uses the interface's __adapt__ method, but that method actually uses a global registry. Neither PyProtocols nor Zope make much use of actually implementing hand-coded __conform__ or __adapt__ methods, as it's too much trouble for something that's so inherently declarative anyway, and only the creator of the object class or the interface's type have any ability to define adapters that way. Given that built-in types are often handy sources of adaptation (e.g. str-to-StringIO in your example), it isn't practical in present-day Python to add a __conform__ method to the str type! Thus, in the general case it just seems easier to use a per-interface or global registry for most normal adaptation, rather than using __conform__. However, having __conform__ exist is a nice out for implementing unusual custom requirements (like easy dynamic conformance), so I don't think it should be removed. ___ Python-Dev mailing list Python-Dev@python.org http://mail.python.org/mailman/listinfo/python-dev Unsubscribe: http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com