Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-15 Thread Alex Martelli
On 2005 Jan 15, at 01:02, Glyph Lefkowitz wrote:
...
Now, we have nowhere to hide PointPen's state on SegmentPen - and why
were we trying to in the first place?  It's a horrible breach of
encapsulation.  The whole *point* of adapters is to convert between
*different* interfaces, not merely to rename methods on the same
interface, or to add extra methods that work on the same data.  To me,
A common implementation technique, when you'd love to associate some 
extra data to an object, but can't rely on the object having a __dict__ 
to let you do that conveniently, is to have an auxiliary dict of 
bunches of extra data, keyed by object's id().  It's a bit messier, in 
that you have to deal with cleanup issues when the object goes away, as 
well as suffer an extra indirectness; but in many use cases it's quite 
workable.  I don't see doing something like
myauxdict[id(obj)] = {'foo': 'bar'}
as "terribly invasive", and therefore neither do I see
obj.myauxfoo = 'bar'
as any more invasive -- just two implementation techniques for the same 
task with somewhat different tradeoffs.  The task, associating extra 
data with obj without changing obj type's source, won't just go away.

Incidentally, the realization of this equivalence was a key step in my 
very early acceptance of Python.  In the first few days, the concept 
"some external code might add an attribute to obj -- encapsulation 
breach!" made me wary; then CLICK, the first time I had to associate 
extra data to an object and realized the alleged ``breach'' was just a 
handy implementation help for the task I needed anyway, I started 
feeling much better about it.

Adapter use cases exist for all three structures:
1. the adapter just needs to change method names and signatures or 
combine existing methods of the object, no state additions;
2. the adapter needs to add some per-object state, which must be shared 
among different adapters which may simultaneously exist on the same 
object;
3. the adapter needs to add some per-adapter state, which must be 
distinct among different adapters which may simultaneously exist on the 
same object.

Case [1] is simplest because you don't have to wonder whether [2] or 
[3] are better, which may be why it's being thought of as "best".  Case 
[3] may be dubious when we talk about AUTOMATIC adaptation, because in 
[3] making and using two separate adapters has very different semantics 
from making just one adapter and using it twice.  When you build the 
adapter explicitly of course you have full control and hopefully 
awareness of that.  For example, in Model/View, clearly you want 
multiple views on the same model and each view may well need a few 
presentation data of its own; if you think of it as adaptation, it's 
definitely a [3].  But do we really want _automatic_ adaptation -- 
passing a Model to a function which expects a View, and having some 
kind of default presentation data be used to make a default view on it? 
 That, I guess, is the dubious part.


"different interfaces" means that the actual meaning of the operations
is different - sometimes subtly, sometimes dramatically.  There has to
be enough information in one interface to get started on the
implementation of another, but the fact that such information is
necessary doesn't mean it is sufficient.  It doesn't mean that there is
enough information in the original object to provide a complete
implementation of a different interface.
If there were enough information, why not just implement all of your
interfaces on the original class?  In the case of our hypothetical
cSegmentPen, we *already* have to modify the implementation of the
original class to satisfy the needs of a "stateless" adapter.  When
you're modifying cSegmentPen, why not just add the methods that you
wanted in the first place?
Reason #1: because the author of the cSegmentPen code cannot assume he 
or she knows about all the interfaces to which a cSegmentPen might be 
adapted a la [3].  If he or she provides a __dict__, or makes 
cSegmentPen weakly referenceable, all [3]-like adaptation needs are 
covered at one (heh heh) stroke.


Here's another example: I have a business logic class which lives in an
object database, typically used for a web application.  I convert this
into a desktop application.  Now, I want to adapt IBusinessThunk to
IGtkUIPlug.  In the process of doing so, I have to create a GTK widget,
loaded out of some sort of resource file, and put it on the screen.  I
have to register event handlers which are associated with that adapter.
OK, a typical case of model/view and thus a [3].  The issue is whether 
you want adaptation to be automatic or explicit, in such cases.

Most of the other use-cases I can think of are like the one James
mentions, where we really are using adaptation to shuffle around some
method names and provide simple glossing over totally isomorphic
functionality to provide backwards (or sideways, in the case of
almost-identical libraries provided on di

Re: [Python-Dev] PEP 246: lossless and stateless

2005-01-15 Thread Alex Martelli
On 2005 Jan 15, at 02:30, Phillip J. Eby wrote:
is requested.  It's too bad Python doesn't have some sort of 
deallocation hook you could use to get notified when an object goes 
away.  Oh well.
For weakly referenceable objects, it does.  Giving one to other objects 
would be almost isomorphic to making every object weakly referenceable, 
wouldn't it?  Or am I missing something...?

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: lossless and stateless

2005-01-15 Thread Just van Rossum
Phillip J. Eby wrote:

> At 07:02 PM 1/14/05 -0500, Glyph Lefkowitz wrote:
> >For the sake of argument, let's say that SegmentPen is a C type,
> >which does not have a __dict__, and that PointPen is a Python
> >adapter for it, in a different project.
> 
> There are multiple implementation alternatives possible here; it
> isn't necessary that the state be hidden there.  The point is that,
> given the same SegmentPen, we want to get the same PointPen each time
> we *implicitly* adapt, in order to avoid violating the "naive"
> developer's mental model of what adaptation is -- i.e. an extension
> of the object's state, not a new object with independent state.
> 
> One possible alternative implementation is to use a dictionary from
> object id to a 'weakref(ob),state' tuple, with the weakref set up to
> remove the entry when 'ob' goes away.  Adapters would then have a
> pointer to their state object and a pointer to the adaptee.  As long
> as an adapter lives, the adaptee lives, so the state remains valid. 
> Or, if no adapters remain, but the adaptee still lives, then so does
> the state which can be resurrected when a new adapter is requested. 
> It's too bad Python doesn't have some sort of deallocation hook you
> could use to get notified when an object goes away.  Oh well.

That sounds extremely complicated as apposed to just storing the sate
where it most logically belongs: on the adapter. And all that to work
around a problem that I'm not convinced needs solving or even exists. At
the very least *I* don't care about it in my use case.

> Anyway, as you and I have both pointed out, sticky adaptation is an 
> important use case; when you need it, you really need it.

Maybe I missed it, but was there an example posted of when "sticky
adaptation" is needed?

It's not at all clear to me that "sticky" behavior is the best default
behavior, even with implicit adoptation. Would anyone in their right
mind expect the following to return [0, 1, 2, 3, 4, 5] instead of [0, 1,
2, 0, 1, 2]?

  >>> from itertools import *
  >>> seq = range(10)
  >>> list(chain(islice(seq, 3), islice(seq, 3)))
  [0, 1, 2, 0, 1, 2]
  >>> 

Just
___
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: lossless and stateless

2005-01-15 Thread Paul Moore
On Fri, 14 Jan 2005 20:06:22 -0500, Phillip J. Eby
<[EMAIL PROTECTED]> wrote:
> >My feeling here was not that people thought that stateless adapters
> >were in general intrinsically better -- just when the adaptation was
> >going to be done implicitly (e.g. by type declarations).
> 
> Yes, exactly. :)

In which case, given that there is no concept in PEP 246 of implicit
adaptation, can we please make a clear separation of this discussion
from PEP 246? (The current version of the PEP makes no mention of
transitive adaptation, as optional or required behaviour, which is the
only other example of implicit adaptation I can think of).

I think there are the following distinct threads of discussion going
on at the moment:

* Details of what should be in PEP 246
* Discussions spinning off from Guido's type-declaration-as-adaptation proposal
* Discussion of what counts as a "good" adapter
* Philip's new generic function / ducy typing proposals

Is that even close to others' understanding?

Just trying to keep my brain from exploding :-)

Paul.
___
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: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 10:39 AM 1/15/05 +0100, Just van Rossum wrote:
That sounds extremely complicated as apposed to just storing the sate
where it most logically belongs: on the adapter.
Oh, the state will be on the adapter all right.  It's just that for type 
declarations, I'm saying the system should return the *same* adapter each time.

 And all that to work
around a problem that I'm not convinced needs solving or even exists. At
the very least *I* don't care about it in my use case.
> Anyway, as you and I have both pointed out, sticky adaptation is an
> important use case; when you need it, you really need it.
Maybe I missed it, but was there an example posted of when "sticky
adaptation" is needed?
No; but Glyph and I have independent use cases for them.  Here's one of 
mine: code generation from a UML or MOF model.  The model classes can't 
contain methods or data for doing code generation, unless you want to cram 
every possible kind of code generation into them.  The simple thing to do 
is to adapt them to a PythonCodeGenerator or an SQLCodeGenerator or 
what-have-you, and to do so stickily.  (Because a code generator may need 
to walk over quite a bit of the structure while keeping state for different 
things being generated.)

You *could* keep state in an external dictionary, of course, but it's much 
easier to use sticky adapters.


It's not at all clear to me that "sticky" behavior is the best default
behavior, even with implicit adoptation. Would anyone in their right
mind expect the following to return [0, 1, 2, 3, 4, 5] instead of [0, 1,
2, 0, 1, 2]?
  >>> from itertools import *
  >>> seq = range(10)
  >>> list(chain(islice(seq, 3), islice(seq, 3)))
  [0, 1, 2, 0, 1, 2]
  >>>
I don't understand why you think it would.  What does islice have to do 
with adaptation?

___
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: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 01:20 PM 1/15/05 +, Paul Moore wrote:
I think there are the following distinct threads of discussion going
on at the moment:
* Details of what should be in PEP 246
* Discussions spinning off from Guido's type-declaration-as-adaptation 
proposal
My understanding was that the first needed to be considered in context of 
the second, since it was the second which gave an implicit blessing to the 
first.  PEP 246 had languished in relative obscurity for a long time until 
Guido's blessing it for type declarations brought it back into the 
spotlight.  So, I thought it important to frame its discussion in terms of 
its use for type declaration.


* Discussion of what counts as a "good" adapter
Alex was originally trying to add to PEP 246 some recommendations regarding 
"good" vs. "bad" adaptation, so this is actually part of "what should be in 
PEP 246"


* Philip's new generic function / ducy typing proposals
And of course this one is an attempt to unify everything and replace PEP 
245 (not 246) with a hopefully more pythonic way of defining interfaces and 
adapters.  I hope to define a "relatively safe" subset of PEP 246 for type 
declarations that can be done automatically by Python, in a way that's also 
conceptually compatible with COM and Java casting (possibly making Jython 
and IronPython's lives a little easier re: type declarations).

___
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: lossless and stateless

2005-01-15 Thread Just van Rossum
Phillip J. Eby wrote:

> >It's not at all clear to me that "sticky" behavior is the best
> >default behavior, even with implicit adoptation. Would anyone in
> >their right mind expect the following to return [0, 1, 2, 3, 4, 5]
> >instead of [0, 1, 2, 0, 1, 2]?
> >
> >   >>> from itertools import *
> >   >>> seq = range(10)
> >   >>> list(chain(islice(seq, 3), islice(seq, 3)))
> >   [0, 1, 2, 0, 1, 2]
> >   >>>
> 
> I don't understand why you think it would.  What does islice have to
> do with adaptation?

islice() takes an iterator, yet I give it a sequence. It calls
iter(seq), which I see as a form of adaptation (maybe you don't). Sticky
adaptation would not be appropriate here, even though the adaptation is
implicit.

Just
___
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: Re: PEP 246: LiskovViolation as a name

2005-01-15 Thread Terry Reedy

"Skip Montanaro" <[EMAIL PROTECTED]> wrote in message 
news:[EMAIL PROTECTED]
> The first example here:
>http://www.compulink.co.uk/~querrid/STANDARD/lsp.htm
> Looks pretty un-extreme to me.

To both summarize and flesh out the square-rectangle example:
Q. Is a square 'properly' a rectangle? A. Depends on 'square' and 
'rectangle'.
* A static, mathematical square is a static, mathematical rectangle just 
fine,
once width and height are aliased (adapted?) to edge.  The only 'behaviors'
are to report size and possibly derived quantities like diagonal and area.
* Similarly, a dynamic, zoomable square is a zoomable rectangle.
* But a square cannot 'properly' be a fully dynamic rectangle that can 
mutate to a dissimilar shape, and must when just one dimension is changed
-- unless shape mutation is allowed to fail or unless the square is allowed 
to mutate itself into a rectangle.

So it seems easily possible to introduce Liskov violations when adding 
behavior to a general superclass.

Terry J. Reedy



___
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: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 05:32 PM 1/15/05 +0100, Just van Rossum wrote:
Phillip J. Eby wrote:
> >It's not at all clear to me that "sticky" behavior is the best
> >default behavior, even with implicit adoptation. Would anyone in
> >their right mind expect the following to return [0, 1, 2, 3, 4, 5]
> >instead of [0, 1, 2, 0, 1, 2]?
> >
> >   >>> from itertools import *
> >   >>> seq = range(10)
> >   >>> list(chain(islice(seq, 3), islice(seq, 3)))
> >   [0, 1, 2, 0, 1, 2]
> >   >>>
>
> I don't understand why you think it would.  What does islice have to
> do with adaptation?
islice() takes an iterator, yet I give it a sequence.
No, it takes an *iterable*, both practically and according to its 
documentation:

>>> help(itertools.islice)
Help on class islice in module itertools:
class islice(__builtin__.object)
 |  islice(iterable, [start,] stop [, step]) --> islice object
 |
 | ... [snip rest]
If you think about the iterator and iterable protocols a bit, you'll see 
that normally the adaptation goes the *other* way: you can pass an iterator 
to something that expects an iterable, as long as it doesn't need 
reiterability.

___
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: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 10:35 AM 1/15/05 +0100, Alex Martelli wrote:
On 2005 Jan 15, at 02:30, Phillip J. Eby wrote:
is requested.  It's too bad Python doesn't have some sort of deallocation 
hook you could use to get notified when an object goes away.  Oh well.
For weakly referenceable objects, it does.  Giving one to other objects 
would be almost isomorphic to making every object weakly referenceable, 
wouldn't it?  Or am I missing something...?
I meant if there was some way to listen for a particular object's 
allocation, like sticking all the pointers you were interested in into a 
big dictionary with callbacks and having a callback run whenever an 
object's refcount reaches zero.  It's doubtless completely impractical, 
however.  I think we can probably live with only weak-referenceable objects 
being seamlessly sticky, if that's a word.  :)

Actually, I've just gotten to the part of the PEP where I have to deal with 
stateful adapters and state retention, and I think I'm going to use this 
terminology for the three kinds of adapters:

* operations (no adapter class needed)
* extenders (operations + a consistent state that conceptually adds state 
to the base object rather than creating an object w/separate lifetime)

* "volatile", "inconsistent", or "disposable" adapters (state may be lost 
or multiplied if passed to different routines)

The idea is to make it really easy to make any of these, but for the last 
category you should have to explicitly declare that you *want* volatility 
(or at least that you are willing to accept it, if the target type is not 
weak-referenceable).

In this way, all three kinds of adaptation may be allowed, but it takes one 
extra step to create a potentially "bad" adapter.  Right now, people often 
create volatile adapters even if what they want is an extender ("sticky 
adapter"), because it's more work to make a functioning extender, not 
because they actually want volatility.

So, let's reverse that and make it easier to create extenders than it is to 
create volatile adapters.  And, since in some cases an extender won't be 
possible even when it's what you want, we could go ahead and allow type 
declarations to make them, as long as the creator has specified that 
they're volatile.

Meanwhile, all three kinds of adapters should avoid accidental implicit 
transitivity by only adapting the "original object".  (Unless, again, there 
is some explicit choice to do otherwise.)  This makes the type declaration 
system a straightforward extension of the COM QueryInterface and Java 
casting models, where an object's "true identity" is always preserved 
regardless of which interface you access its operations through.

___
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: lossless and stateless

2005-01-15 Thread Simon Percivall
On 2005-01-15, at 18.06, Phillip J. Eby wrote:
At 05:32 PM 1/15/05 +0100, Just van Rossum wrote:
Phillip J. Eby wrote:
> >It's not at all clear to me that "sticky" behavior is the best
> >default behavior, even with implicit adoptation. Would anyone in
> >their right mind expect the following to return [0, 1, 2, 3, 4, 5]
> >instead of [0, 1, 2, 0, 1, 2]?
> >
> >   >>> from itertools import *
> >   >>> seq = range(10)
> >   >>> list(chain(islice(seq, 3), islice(seq, 3)))
> >   [0, 1, 2, 0, 1, 2]
> >   >>>
>
> I don't understand why you think it would.  What does islice have to
> do with adaptation?
islice() takes an iterator, yet I give it a sequence.
No, it takes an *iterable*, both practically and according to its 
documentation:
But it _does_ perform an implicit adaptation, via PyObject_GetIter. A 
list has no next()-method, but iter(list()) does.

//Simon
___
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: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 10:48 PM 1/15/05 +0100, Simon Percivall wrote:
On 2005-01-15, at 18.06, Phillip J. Eby wrote:
At 05:32 PM 1/15/05 +0100, Just van Rossum wrote:
Phillip J. Eby wrote:
> >It's not at all clear to me that "sticky" behavior is the best
> >default behavior, even with implicit adoptation. Would anyone in
> >their right mind expect the following to return [0, 1, 2, 3, 4, 5]
> >instead of [0, 1, 2, 0, 1, 2]?
> >
> >   >>> from itertools import *
> >   >>> seq = range(10)
> >   >>> list(chain(islice(seq, 3), islice(seq, 3)))
> >   [0, 1, 2, 0, 1, 2]
> >   >>>
>
> I don't understand why you think it would.  What does islice have to
> do with adaptation?
islice() takes an iterator, yet I give it a sequence.
No, it takes an *iterable*, both practically and according to its 
documentation:
But it _does_ perform an implicit adaptation, via PyObject_GetIter.
First, that's not implicit.  Second, it's not adaptation, 
either.  PyObject_GetIter invokes the '__iter__' method of its target -- a 
method that is part of the *iterable* interface.  It has to have something 
that's *already* iterable; it can't "adapt" a non-iterable into an iterable.

Further, if calling a method of an interface that you already have in order 
to get another object that you don't is adaptation, then what *isn't* 
adaptation?  Is it adaptation when you call 'next()' on an iterator? Are 
you then "adapting" the iterator to its next yielded value?

No?  Why not?  It's a special method of the "iterator" interface, just like 
__iter__ is a special method of the "iterable" interface.

So, I can't see how you can call one adaptation, but not the other.  My 
conclusion: neither one is adaptation.


 A list has no next()-method, but iter(list()) does.
But a list has an __iter__ method, so therefore it's an iterable.  That's 
what defines an iterable: it has an __iter__ method.  It would only be 
adaptation if lists *didn't* have an __iter__ method.

___
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: lossless and stateless

2005-01-15 Thread Just van Rossum
Phillip J. Eby wrote:

> >But it _does_ perform an implicit adaptation, via PyObject_GetIter.
> 
> First, that's not implicit.  Second, it's not adaptation, either. 
> PyObject_GetIter invokes the '__iter__' method of its target -- a
> method that is part of the *iterable* interface.  It has to have
> something that's *already* iterable; it can't "adapt" a non-iterable
> into an iterable.
> 
> Further, if calling a method of an interface that you already have in
> order to get another object that you don't is adaptation, then what
> *isn't* adaptation?  Is it adaptation when you call 'next()' on an
> iterator? Are you then "adapting" the iterator to its next yielded
> value?

That's one (contrived) way of looking at it. Another is that

  y = iter(x)

adapts the iterable protocol to the iterator protocol. I don't (yet) see
why a bit of state disqualifies this from being called adaptation.

> No?  Why not?  It's a special method of the "iterator" interface,
> just like __iter__ is a special method of the "iterable" interface.

The difference it that the result of .next() doesn't have a specified
interface.

> So, I can't see how you can call one adaptation, but not the other. 
> My conclusion: neither one is adaptation.

Maybe...

Just
___
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: lossless and stateless

2005-01-15 Thread Simon Percivall
On 2005-01-15, at 23.50, Just van Rossum wrote:
Phillip J. Eby wrote:
But it _does_ perform an implicit adaptation, via PyObject_GetIter.
First, that's not implicit.  Second, it's not adaptation, either.
PyObject_GetIter invokes the '__iter__' method of its target -- a
method that is part of the *iterable* interface.  It has to have
something that's *already* iterable; it can't "adapt" a non-iterable
into an iterable.
Further, if calling a method of an interface that you already have in
order to get another object that you don't is adaptation, then what
*isn't* adaptation?  Is it adaptation when you call 'next()' on an
iterator? Are you then "adapting" the iterator to its next yielded
value?
That's one (contrived) way of looking at it. Another is that
  y = iter(x)
adapts the iterable protocol to the iterator protocol.
Especially since an iterable can also be an object without an __iter__
method but with a __getitem__ method. Calling __iter__ might get an
iterator, but calling __getitem__ does not. That seems like adaptation.
No? It's still not clear to me, as this shows, exactly what counts as
what in this game.
//Simon
___
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: lossless and stateless

2005-01-15 Thread James Y Knight
On Jan 15, 2005, at 6:02 PM, Simon Percivall wrote:
On 2005-01-15, at 23.50, Just van Rossum wrote:
Phillip J. Eby wrote:
But it _does_ perform an implicit adaptation, via PyObject_GetIter.
First, that's not implicit.  Second, it's not adaptation, either.
PyObject_GetIter invokes the '__iter__' method of its target -- a
method that is part of the *iterable* interface.  It has to have
something that's *already* iterable; it can't "adapt" a non-iterable
into an iterable.
Further, if calling a method of an interface that you already have in
order to get another object that you don't is adaptation, then what
*isn't* adaptation?  Is it adaptation when you call 'next()' on an
iterator? Are you then "adapting" the iterator to its next yielded
value?
That's one (contrived) way of looking at it. Another is that
  y = iter(x)
adapts the iterable protocol to the iterator protocol.
Especially since an iterable can also be an object without an __iter__
method but with a __getitem__ method. Calling __iter__ might get an
iterator, but calling __getitem__ does not. That seems like adaptation.
No? It's still not clear to me, as this shows, exactly what counts as
what in this game.
I think that's wrong. To spell iter() in an adapter/interface world, 
I'd spell iter(obj) as:
  adapt(obj, IIterable).iterator()

Then, list, tuple, dict objects would specify that they implement 
IIterable. There is a default adapter from object->IIterable which 
provides a .iterate() method which creates an iterator that uses 
__getitem__ on the adaptee.

In my opinion, adapters provide a different view of an object. I can 
see treating list "as a" iterable, but not "as a" iterator.

James
___
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] Exceptions *must*? be old-style classes?

2005-01-15 Thread Jim Jewett
Phillip J. Eby wrote (in
http://mail.python.org/pipermail/python-dev/2005-January/050854.html)

> * Classic class support is a must; exceptions are still required to be 
> classic, and even if they weren't in 2.5, backward compatibility should be 
> provided for at least one release.

The base of the Exception hierarchy happens to be a classic class.
But why are they "required" to be classic?

More to the point, is this a bug, a missing feature, or just a bug in 
the documentation for not mentioning the restriction?

You can inherit from both Exception and object.  (Though it turns out
you can't raise the result.)  My first try with google failed to produce an
explanation -- and I'm still not sure I understand, beyond "it doesn't
happen to work at the moment."  Neither the documentation nor the 
tutorial mention this restriction.

http://docs.python.org/lib/module-exceptions.html
http://docs.python.org/tut/node10.html#SECTION001050

I didn't find any references to this restriction in exception.c.  I did find
some code implying this in errors.c and ceval.c, but that wouldn't have 
caught my eye if I weren't specifically looking for it *after* having just
read the discussion about (rejected) PEP 317.  

-jJ
___
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] Exceptions *must*? be old-style classes?

2005-01-15 Thread Guido van Rossum
> The base of the Exception hierarchy happens to be a classic class.
> But why are they "required" to be classic?
> 
> More to the point, is this a bug, a missing feature, or just a bug in
> the documentation for not mentioning the restriction?

It's an unfortunate feature; it should be mentioned in the docs; it
should also be fixed, but fixing it isn't easy (believe me, or it
would have been fixed in Python 2.2).

To be honest, I don't recall the exact reasons why this wasn't fixed
in 2.2; I believe it has something to do with the problem of
distinguishing between string and class exception, and between the
various forms of raise statements.

I think the main ambiguity is raise "abc", which could be considered
short for raise str, "abc", but that would be incompatible with except
"abc". I also think that the right way out of there is to simply
hardcode a check that says that raise "abc" raises a string exception
and raising any other instance raises a class exception. But there's a
lot of code that has to be changed.

It's been suggested that all exceptions should inherit from Exception,
but this would break tons of existing code, so we shouldn't enforce
that until 3.0. (Is there a PEP for this? I think there should be.)

-- 
--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] PEP 246: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 11:50 PM 1/15/05 +0100, Just van Rossum wrote:
Phillip J. Eby wrote:
> >But it _does_ perform an implicit adaptation, via PyObject_GetIter.
>
> First, that's not implicit.  Second, it's not adaptation, either.
> PyObject_GetIter invokes the '__iter__' method of its target -- a
> method that is part of the *iterable* interface.  It has to have
> something that's *already* iterable; it can't "adapt" a non-iterable
> into an iterable.
>
> Further, if calling a method of an interface that you already have in
> order to get another object that you don't is adaptation, then what
> *isn't* adaptation?  Is it adaptation when you call 'next()' on an
> iterator? Are you then "adapting" the iterator to its next yielded
> value?
That's one (contrived) way of looking at it. Another is that
  y = iter(x)
adapts the iterable protocol to the iterator protocol. I don't (yet) see
why a bit of state disqualifies this from being called adaptation.
Well, if you go by the GoF "Design Patterns" book, this is actually what's 
called an "Abstract Factory":

   "Abstract Factory: Provide an interface for creating ... related or 
dependent objects without specifying their concrete classes."

So, 'iter()' is an abstract factory that creates an iterator without 
needing to specify the concrete class of iterator you want.  This is a much 
closer fit for what's happening than the GoF description of "Adapter":

   "Adapter: Convert the interface of a class into another interface 
clients expect.  Adapter lets classes work together that couldn't otherwise 
because of incompatible interfaces."

IMO, it's quite "contrived" to try and squeeze iteration into this concept, 
compared to simply saying that 'iter()' is an abstract factory that creates 
"related or dependent objects".

While it has been pointed out that the GoF book is not handed down from 
heaven or anything, its terminology is certainly widely used to describe 
certain patterns of programming.  If you read their full description of the 
adapter pattern, nothing in it is about automatically getting an adapter 
based on an interface.  It's just about the idea of *using* an adapter that 
you already have, and it's strongly implied that you only use one adapter 
for a given source and destination that need adapting, not create lots of 
instances all over the place.

So really, PEP 246 'adapt()' (like 'iter()') is more about the Abstract 
Factory pattern.  It just happens in the case of PEP 246 that it's an 
Abstract Factory that *can* create adapters, but it's not restricted to 
handing out *just* adapters.  It can also be used to create views, 
iterators, and whatever else you like.  But that's precisely what makes it 
problematic for use as a type declaration mechanism, because you run the 
risk of it serving up entirely new objects that aren't just interface 
transformers.  And of course, that's why I think that you should have to 
declare that you really want to use it for type declarations, if in fact 
it's allowed at all.  Explicit use of 'adapt()', on the other hand, can 
safely create whatever objects you want.

Oh, one other thing -- distinguishing between "adapters" and merely 
"related" objects allows you to distinguish whether you should adapt the 
object or what it wraps.  A "related" object (like an iterator) is a 
separate object, so it's safe to adapt it to other things.  An actual 
*adapter* is not a separate object, it's an extension of the object it 
wraps.  So, it should not be re-adapted when adapting again; instead the 
underlying object should be adapted.

So, while I support in principle all the use cases for "adaptation" 
(so-called) that have been discussed here, I think it's important to refine 
our terminology to distinguish between GoF "adapters" and "things you might 
want to create with an abstract factory", because they have different 
requirements and support different use cases.

We have gotten a little bogged down by our comparisons of "good" and "bad" 
adapters; perhaps to move forward we should distinguish between "adapters" 
and "views", and say that an iterator is an example of a view: you may have 
more than one view on the same thing, and although a view depends on the 
thing it "views", it doesn't really "convert an interface"; it provides 
distinct functionality on a per-view basis.

Currently, PEP 246 'adapt()' is used "in the field" to create both adapters 
and views, because 1) it's convenient, and 2) it can.  :)  However, for 
type declarations, I think it's important to distinguish between the two, 
to avoid implicit creation of additional views.

A view needs to be managed within the scope that it applies to.  By that, I 
mean for example that a 'for' loop creates an iterator view and then 
manages it within the scope of the loop.  However, if you need the iterator 
to remain valid outside the 'for' loop, you may need to first call 'iter()' 
to get an explicit iterator you can hold on to.

Similarly, if you have a file that you are

Re: [Python-Dev] Exceptions *must*? be old-style classes?

2005-01-15 Thread Simon Percivall
On 2005-01-16, at 02.57, Guido van Rossum wrote:
It's been suggested that all exceptions should inherit from Exception,
but this would break tons of existing code, so we shouldn't enforce
that until 3.0. (Is there a PEP for this? I think there should be.)
What would happen if Exception were made a new-style class, enforce
inheritance from Exception for all new-style exceptions, and allow all
old-style exceptions as before. Am I wrong in assuming that only the
most esoteric exceptions inheriting from Exception would break by
Exception becoming new-style?
//Simon
___
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: lossless and stateless

2005-01-15 Thread Phillip J. Eby
At 08:13 PM 1/15/05 -0500, James Y Knight wrote:
On Jan 15, 2005, at 6:02 PM, Simon Percivall wrote:
On 2005-01-15, at 23.50, Just van Rossum wrote:
Phillip J. Eby wrote:
But it _does_ perform an implicit adaptation, via PyObject_GetIter.
First, that's not implicit.  Second, it's not adaptation, either.
PyObject_GetIter invokes the '__iter__' method of its target -- a
method that is part of the *iterable* interface.  It has to have
something that's *already* iterable; it can't "adapt" a non-iterable
into an iterable.
Further, if calling a method of an interface that you already have in
order to get another object that you don't is adaptation, then what
*isn't* adaptation?  Is it adaptation when you call 'next()' on an
iterator? Are you then "adapting" the iterator to its next yielded
value?
That's one (contrived) way of looking at it. Another is that
  y = iter(x)
adapts the iterable protocol to the iterator protocol.
Especially since an iterable can also be an object without an __iter__
method but with a __getitem__ method. Calling __iter__ might get an
iterator, but calling __getitem__ does not. That seems like adaptation.
No? It's still not clear to me, as this shows, exactly what counts as
what in this game.
I think that's wrong. To spell iter() in an adapter/interface world, I'd 
spell iter(obj) as:
  adapt(obj, IIterable).iterator()

Then, list, tuple, dict objects would specify that they implement 
IIterable. There is a default adapter from object->IIterable which 
provides a .iterate() method which creates an iterator that uses 
__getitem__ on the adaptee.

In my opinion, adapters provide a different view of an object. I can see 
treating list "as a" iterable, but not "as a" iterator.
Uh oh.  I just used "view" to describe an iterator as a view on an 
iterable, as distinct from an adapter that adapts a sequence so that it's 
iterable.  :)

I.e., using "view" in the MVC sense where a given Model might have multiple 
independent Views.

We really need to clean up our terminology somehow, and I may need to 
rewrite some parts of my PEP-in-progress.  I had been using the term 
"volatile adapter" for what I'd written so far, but by the time I got to 
the part where I had to explain how to actually *make* volatile adapters, I 
realized that I was right before: they aren't adapters just because PEP 246 
'adapt()' can be used to create them.  They're just something *else* that's 
convenient to create with 'adapt()' besides adapters.  Calling them even 
"volatile adapters" just confuses them with "real" adapters.

On the *other* hand, maybe we should just call GoF adapters "extenders" 
(since they extend the base object with a new interface or extended 
functionality, but aren't really separate objects) and these other things 
like iterators and views should be called "accessories", which implies you 
have lots of them and although they "accessorize" an object, they are 
themselves individual objects.  (Whereas an extender becomes conceptually 
"part of" the thing it extends.)

It's then also clearer that it makes no sense to have a type declaration 
ever cause you to end up with a new accessory, as opposed to an extender 
that's at least figuratively always there.

What do y'all think?  Is that a better way to distinguish kinds of 
"adapters"?  (I.e. extenders versus accessories)  Or does somebody have 
better words we can use?

___
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] Exceptions *must*? be old-style classes?

2005-01-15 Thread Phillip J. Eby
At 05:57 PM 1/15/05 -0800, Guido van Rossum wrote:
It's been suggested that all exceptions should inherit from Exception,
but this would break tons of existing code, so we shouldn't enforce
that until 3.0. (Is there a PEP for this? I think there should be.)
Couldn't we require new-style exceptions to inherit from Exception?  Since 
there are no new-style exceptions that work now, this can't break existing 
code.  Then, the code path is just something like:

if isinstance(ob,Exception):
# it's an exception, use its type
else:
# all the other tests done now
This way, the other tests that would be ambiguous wrt new-style classes can 
be skipped, but non-Exception classic classes would still be handled by the 
existing checks.

Or am I missing something?
___
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, Feedback Request

2005-01-15 Thread Clark C. Evans
I started to edit the PEP, but found that we really don't have any
consensus on a great many items. The following is a bunch of topics,
and a proposed handling of those topics.  A bulk of this comes from
a phone chat I had with Alex this past afternoon, and other items
come from my understanding of the mailing list, or prior conversations
with Phillip, among others.  It's a strawman.

I'd really very much like feedback on each topic, preferably only
one post per person summarizing your position/suggestions.  I'd
rather not have a run-away discussion on this post.

---
-
  topic: a glossary
  overview:
It seems that we are having difficulty with words that have shifting
definitions.  The next PEP edit will need to add a glossary that 
nails down some meanings of these words.  Following are a few 
proposed terms/meanings.
  proposal:
  - protocol means any object, usually a type or class or interface,
which guides the construction of an adapter
  - adaptee is the object which is to be adapted, the original object
  - adaptee-class refers to the adaptee's class
  - adapter refers to the result of adapting an adaptee to a protocol
  - factory refers to a function, f(adaptee) -> adapter, where 
the resulting adapter complies with a given protocol
  feedback:
Much help is needed here; either respond to this thread with
your words and definitions, or email them directly to Clark 
and he will use your feedback when creating the PEP's glossary.
-
  topic: a registry mechanism
  overview:
It has become very clear from the conversations the past few
days that a registry is absolutely needed for the kind of adapt()
behavior people are currently using in Zope, Twisted, and Peak.
  proposal:
  - The PEP will define a simple and flexible registry mechanism.
  - The registry will be a mapping from a (adaptee-class, protocol) 
pair to a corresponding factory.
  - Only one active registration per pair (see below)
  feedback:
We welcome/encourage experiences and concreate suggestions from
existing registries.  Our goal is to be minimal, extensible,
and sufficient.  See other topics for more specific concerns
before you comment on this more general topic.
-
  topic: should 'object' be impacted by PEP 246
  overview:
The semantics of exceptions depend if 'object' is given a
default __conform__ method (which would do isinstance), in which
case, returning None in a subclass could be used to prevent
Liskov violations. However, by requiring a change to 'object',
it may hinder adoption or slow-down testing.
  proposal:
  - We will not ask/require changes to `object'.
  - Liskov violations will be managed via the registry, see below.
  - This is probably faster for isinstance cases?
  feedback:
If you really think we should move isinstance() into
object.__conform__, then here is your chance to make a final
stand. ;)
-
  topic: adaption stages
  overview:
There are several stages for adaptation.  It was recommended
that the 'registry' be the first stop in the chain. 
  proposal:
  - First, the registry is checked for a suitable adapter
  - Second, isinstance() is checked, the adaptee is an instance
of the protocol, adaptation ends and adaptee is returned.
  - Third, __conform__ on the adaptee is called with the given
protocol being requested.
  - Fourth, __adapt__ on the protocol is called, with the given
adaptee.
  feedback:
This largely dependent upon the previous topic, but if something
isn't obvious (mod exceptions below), please say something.
-
  topic: module vs built-in
  overview:
Since we will be adding a registry, exceptions, and other items,
it probably makes sense to use a module for 'adapt'.
  proposal:
  - PEP 246 will ask for a `adapt' module, with an `adapt' function.
  - The registry will be contained in this module, 'adapt.register'
  - The `adapt' module can provide commonly-used adapter factories,
such as adapt.Identity.
  - With a standardized signature, frameworks can provide their own
'local' registry/adapt overrides.
  feedback:
Please discuss the merits of a module approach, and if having
local registries is important (or worth the added complexity).
Additional suggestions on how the module should be structured
are welcome. 
-
  topic: exception handling
  overview:
How should adaption stages progress and exceptions be handled.
There were problems with swallowed TypeError exceptions in 
the 2001 version of the PEP, type errors are not swallowed.
  proposal:
  - The 'adapt' module will define an adapt.AdaptError(TypeError).
  - At any stage of adaptation, if None is returned, the adaptation
continues to the next stage.
  - Any exception other than adapt.AdaptException(TypeError)
causes the adapt() call to fail, and the exception to be 
raised to the caller of adapt(); the 'default' value is not
returned in this case.
  - At 

Re: [Python-Dev] PEP 246, Feedback Request

2005-01-15 Thread Phillip J. Eby
At 11:04 PM 1/15/05 -0500, Clark C. Evans wrote:
  topic: a glossary
  overview:
It seems that we are having difficulty with words that have shifting
definitions.  The next PEP edit will need to add a glossary that
nails down some meanings of these words.  Following are a few
proposed terms/meanings.
It would also be helpful to distinguish between 1-to-1 "as a" adapters, and 
1-to-many "view" adapters.  There isn't a really good terminology for this, 
but it's important at least as it relates to type declarations.


  - Any exception other than adapt.AdaptException(TypeError)
causes the adapt() call to fail, and the exception to be
raised to the caller of adapt(); the 'default' value is not
returned in this case.
  - At any stage of adaption, if adapt.AdaptException(TypeError) is
raised, then the adaptation process stops, as if None had been
returned from each stage.
  - If all adaption stages return None, there are two cases.  If the
call to adapt() had a 'default' value, then this is returned;
otherwise, an adapt.AdaptException is raised.
-1; This allows unrelated AdaptExceptions to end up being silently 
caught.  These need to be two different exceptions if you want to support 
stages being able to "veto" adaptation.  Perhaps you should have a distinct 
VetoAdaptation error to support that use case.


  topic: transitivity
  ...
  proposal:
  ...
  feedback:
I'm looking for warts in this plan, and verification if
something like this has been done -- comments how well
it works.  Alternative approaches?
I'll try to think some more about this one later, but I didn't see any 
obvious problems at first glance.


  topic: declaration (aka Guido's syntax) and intrinsic adaption
  overview:
Guido would like his type declaration syntax (see blog entry) to
be equivalent to a call to adapt() without any additional
arguments.  However, not all adapters should be created in the
context of a declaration -- some should be created more
explicitly.  We propose a mechanism where an adapter factory can
register itself as not suitable for the declaration syntax.
It would be much safer to have the reverse be the default; i.e., it should 
take special action to declare an adapter as being *suitable* for use with 
type declarations.

IOW, sticky intrinsic adapters should be the default, and volatile 
accessories should take an extra action to make them usable with type 
declarations.


  feedback:
This is the simplest solution I heard on the list; the word
'intrinsic' was given by Alex.  Is there a better word?
Sadly, no.  I've been playing with words like "extender", "mask", 
"personality" etc. to try and find a name for a thing you only reasonably 
have one of, versus things you can have many of like "accessory", "add-on", 
etc.


  topic: adaptee (aka origin)
  overview:
There was discussion as to how to get back to the original
object from an adapter.  Is this in scope of PEP 246?
  proposal:
  - we specify an __adaptee__ property, to be optionally implemented
by an adapter that provides a reference adaptee
  - the adapt.register method has an optional argument, 'adaptee',
that defaults to False; if it is True, adapt() calls will stuff
away into a weak-reference mapping from adapter to adaptee.
  - an adapt.adaptee(adaptor) function which returns the given
adaptee for the adaptor; this first checks the weak-reference
table, and then checks for an __adaptee_
  feedback:
Is this useful, worth the complexity?
This is tied directly to intrinsicness and stickyness.  If you are 
intrinsic, you *must* have __adaptee__, so that adapt can re-adapt you 
safely.  If you are intrinsic, you *must* be stateless or 
sticky.  (Stateless can be considered an empty special case of 
"sticky")  So, you might be able to combine a lot of these options to make 
the interface cleaner.

Think of it this way: if the adapter is intrinsic, it's just a 
"personality" of the underlying object.  So you don't want to re-adapt a 
personality, instead you re-adapt the "original object".

But for a non-intrinsic adapter, the adapter is an independent object only 
incidentally related to the original adaptee, so it is now an "original 
object" of its own.


  topic: sticky
  overview:
Sticky adapters, that is, ones where there is only one instance
per adaptee is a common use case.  Should the registry of PEP 246
provide this feature?
Ideally, yes.

  proposal:
  - the adapt.register method has an optional argument, 'sticky',
that defaults to False
Make it default to whatever the 'intrinsic' setting is, because the only 
time you don't care for an intrinsic adapter is if the adapter is 
completely stateless.  Or, better yet, call it 'volatile' or something and 
default to False.  (I.e, you have to be say you're willing to have it 
volatile.)

If you get all of these features, it's going to come mighty close to the 
functiona

[Python-Dev] "Monkey Typing" pre-PEP, partial draft

2005-01-15 Thread Phillip J. Eby
I just attempted to post the Monkey Typing draft pre-PEP, but it bounced 
due to being just barely over the size limit for the list.  :)

So, I'm just posting the preamble and abstract here for now, and a link to 
a Wiki page with the full text.  I hope the moderator will approve the 
actual posting soon so that replies can quote from the text.

=== original message ===
This is only a partial first draft, but the Motivation section nonetheless 
attempts to briefly summarize huge portions of the various discussions 
regarding adaptation, and to coin a hopefully more useful terminology than 
some of our older working adjectives like "sticky" and "stateless" and 
such.  And the specification gets as far as defining a simple 
decorator-based syntax for creating operational (prev. "stateless") and 
extension (prev. "per-object stateful") adapters.

I stopped when I got to the API for declaring volatile (prev. per-adapter 
stateful) adapters, and for enabling them to be used with type 
declarations, because Clark's post on his revisions-in-progress seem to 
indicate that this can probably be handled within the scope of PEP 246 
itself.  As such, this PEP should then be viewed more as an attempt to 
formulate how "intrinsic" adapters can be defined in Python code, without 
the need to manually create adapter classes for the majority of 
type-compatibility and "extension" use cases.  In other words, the 
implementation described herein could probably become part of the front-end 
for the PEP 246 adapter registry.

Feedback and corrections (e.g. if I've repeated myself somewhere, spelling, 
etc.) would be greatly appreciated.  This uses ReST markup heavily, so if 
you'd prefer to read an HTML version, please see:

http://peak.telecommunity.com/DevCenter/MonkeyTyping
But I'd prefer that corrections/discussion quote the relevant section so I 
know what parts you're talking about.  Also, if you find a place where a 
more concrete example would be helpful, please consider submitting one that 
I can add.  Thanks!

PEP: XXX
Title: "Monkey Typing" for Agile Type Declarations
Version: $Revision: X.XX $
Last-Modified: $Date: 2003/09/22 04:51:50 $
Author: Phillip J. Eby <[EMAIL PROTECTED]>
Status: Draft
Type: Standards Track
Python-Version: 2.5
Content-Type: text/x-rst
Created: 15-Jan-2005
Post-History: 15-Jan-2005
Abstract

Python has always had "duck typing": a way of implicitly defining types by
the methods an object provides.  The name comes from the saying, "if it walks
like a duck and quacks like a duck, it must *be* a duck".  Duck typing has
enormous practical benefits for small and prototype systems.  For very large
frameworks, however, or applications that comprise multiple frameworks, some
limitations of duck typing can begin to show.
This PEP proposes an extension to "duck typing" called "monkey typing", that
preserves most of the benefits of duck typing, while adding new features to
enhance inter-library and inter-framework compatibility.  The name comes from
the saying, "Monkey see, monkey do", because monkey typing works by stating
how one object type may *mimic* specific behaviors of another object type.
Monkey typing can also potentially form the basis for more sophisticated type
analysis and improved program performance, as it is essentially a simplified
form of concepts that are also found in languages like Dylan and Haskell.  It
is also a straightforward extension of Java casting and COM's QueryInterface,
which should make it easier to represent those type systems' behaviors within
Python as well.
[see the web page above for the remaining text]
___
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