[Python-Dev] PEP 342 - Enhanced Iterators

2005-06-13 Thread Delaney, Timothy C (Timothy)
There's a thread on c.l.py at the moment ("Controlling a generator the
pythonic way") which is basically coming up with PEP 342. I've pointed
them to PEP 342, but it's made me think that the name of the PEP could
better indicate what it does.

I propose "Coroutines via Enhanced Iterators".

Tim Delaney
___
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 343 rewrite complete

2005-06-02 Thread Delaney, Timothy C (Timothy)
Phillip J. Eby wrote:

> That's not a bug, it's a feature.  If the object doesn't have a
> 'close()' 
> method, clearly it doesn't need to be closed.  If it's the "wrong"
> object 
> for what you're using it for in the body of the 'with' block, it'll
> show up 
> there, so this doesn't hide any errors.

For those semantics, I think one of the following would be better:

with local(obj):

with scoped(obj):

but those semantics apply better to __enter__ and __exit__ anyway.

I think a "closing adaptor" should only work with objects that have a
close() method.

Perhaps:

with scoped_closable(obj):

Tim Delaney
___
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] Example for PEP 343

2005-05-17 Thread Delaney, Timothy C (Timothy)
Bob Ippolito wrote:

>> One more thought:  Rather than just saving the precision, it is
>> likely wiser, safer, and more general to just save and restore the
>> whole context and let the wrapped block only work with a copy.
>> 
>> oldcontext = decimal.getcontext()
>> newcontext = oldcontext.copy()
>> newcontext.prec += 2
>> yield None
>> decimal.setcontext(oldcontext)
>> 
>> This approach defends against various kinds of unruly behavior by the
>> yield target.
> 
> I think you're missing a decimal.setcontext(newcontext) before the
> yield..

Seems to me this should be in the standard library ;)

Tim Delaney
___
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 343 - Abstract Block Redux

2005-05-15 Thread Delaney, Timothy C (Timothy)
Steven Bethard wrote:

> If I've misunderstood, and there are other situations when
> "needs_finish" is required, it'd be nice to see some more examples.

The other cases are where you want to do something in response to an
exception, but not otherwise::

def gen():
try:
yield
except:
print 'Got exception:', sys.exc_info()
raise

Personally, I think they're rare enough that you could use a decorator
in those cases, but still have::

def gen():
try:
yield
finally:
pass

automatically make the generator conform to the do/with protocol.

Tim Delaney
___
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 343 - Abstract Block Redux

2005-05-15 Thread Delaney, Timothy C (Timothy)
Shane Hathaway wrote:

> PEP 340 is very nice, but it became less appealing to me when I saw
> what  it would do to "break" and "continue" statements.

Absolutely. I really liked PEP 340, but two things stood out to me as
being flawed:

1. Looping - it took a while for me to realise this was bugging me - the
unintuitive behaviour of break and continue clarified it for me.

2. Not re-raising exceptions automatically. I actually proposed at one
point that any exception should be re-raised at the end of the iterator
finalisation unless another exception was raised (not StopIteration,
etc). I still continue to support this. It also deals with the
control-flow issue (being hidden).

PEP 3XX has some other nice things. I have two opposing views on
for-loops supporting finalisation of iterators though:

1. for-loops should support finalisation. However, in that case every
iterator should be finalisable by default, and you should have to go out
of your way to prevent it (or prevent forced exhaustion of the
iterator). I think there's zero chance of this proposal being accepted
;)

2. for-loops should not support finalisation at all, and if you want
finalisation semantics you need to enclose the for-loop in a do/with
statement.

I think the most important thing is that the semantics must be
absolutely clear to someone looking at the code for the first time,
without knowing the particulars of the statement being used. To me that
suggests that the following 3 factors are the most important:

1. Non-looping semantics. Looping semantics require me to think more
about the actual behaviour in the presence of break/continue.

2. An exception raised in the body of the statement must be propagated
outside of the statement. I'm willing to accept another exception being
raised in its place, but in that case I think it would be a good idea to
chain the exceptions in some way. In any case, if the body of the
statement terminates abnormally, it should not be possible for the
statement to change that abnormal exit.

3. There should be a single statement (other than try...finally) that
has finalisation semantics i.e. for-loop doesn't.

Tim Delaney
___
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] Chained Exceptions

2005-05-12 Thread Delaney, Timothy C (Timothy)
James Y Knight wrote:

> Of course you can already do similar with current python, it just
> can't be spelled as nicely, and the default traceback printer won't
> use the info:
> 
> try:
>raise AError
> except:
>newException = BError()
>newException.cause=sys.exc_info()
>raise newException

Well, one thing you can do is (somewhat evil ;)

::

import sys

try:
raise AError, 'message'
except:
exc_type, exc_value, exc_traceback - sys.exc_info()
raise BError, exc_value, exc_traceback

with the result:

Traceback (most recent call last):
File ...
raise AError, 'message'
BError: message

So you store the original exception as the argument to the new exception
(so it's accessible). This has the nice side effect that message is
displayed in the traceback - but the type has changed.

Whilst in the above example, it's particularly evil, in the case where
the original exception came from a function call and you want to
translate the type it works very nicely.

Tim Delaney
___
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 340: Deterministic Finalisation (new PEP draft, either a competitor or update to PEP 340)

2005-05-10 Thread Delaney, Timothy C (Timothy)
Greg Ewing wrote:

> Nick Coghlan wrote:
>> Hmm, with that approach, a code inspection tool like pychecker could
>> be used to pick up the slack, and flag generators which have a yield
>> inside a try/finally or a user defined statement without applying
>> the "needs finalisation" decorator 
> 
> What about giving them an __exit__ method if and only
> if they have a yield inside a try/finally? Old generators
> won't be doing that, because it's currently illegal.

It's possible to create a generator that does not contain a finally, but
still needs cleanup.

def gen():
try:
yield
except:
print 'cleanup'
raise

Tim Delaney
___
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 340 - For loop cleanup, and feature separation

2005-05-05 Thread Delaney, Timothy C (Timothy)
Greg Ewing wrote:

> I'm still bothered by the idea of for-loops not participating
> in the new generator finalization protocol.

I agree - that's always been nagging at me too.

The problem with it is that then you either:

1. Have a guarantee that an iterator will be exhausted when the for loop
exits (as per block statements);

OR

2. Rely on garbage collection (reference counting, etc) to ensure
finalisation.

Personally, I'm of the opinion that we should make a significant break
(no pun intended ;) and have for-loops attempt to ensure that iterators
are exhausted. An iterator could be specifically designed to prevent
that if needed, but in the vast majority of cases an iterator is never
used after the for-loop.

An example of an iterator that was specifically designed to continue
working after its initial for-loop would be::

def gen():
try:
setup1()

try:
yield 1
finally:
cleanup1()

except StopIteration:
pass

setup2()

try:
yield 2
finally:
cleanup2()

This allows cleanup, but then continued usage.

> So I think that, in the interests of least surprise,
> for-loops should provide the same finalization promises
> as block statements.

Agreed.

> If that is done, it becomes easier to decide whether
> the block statement should loop. The answer is probably
> no: If you're writing a loop, you use a for-statement;
> if you're not, you use a block-statement. This helps
> to clearly differentiate the two, and provide
> justification for having two statements.

Agreed.

> I'm also starting to like the idea of having a
> completely separate protocol for block-statements

+1

> and an adaptor of some kind for using generators to
> implement them.

My preference would be direct syntactic support...

Tim Delaney
___
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 340: Breaking out.

2005-05-05 Thread Delaney, Timothy C (Timothy)
Greg Ewing wrote:

> Seems to me it should be up to the block iterator whether
> a break statement gets caught or propagated, since it's
> up to the block iterator whether the construct behaves
> like a loop or not.
> 
> This could be achieved by having a separate exception
> for breaks, as originally proposed.
> 
> If the iterator propagates the Break exception back out,
> the block statement should break any enclosing loop.
> If the iterator wants to behave like a loop, it can
> catch the Break exception and raise StopIteration
> instead.

In this scenario (and I'm not saying I approve or disapprove) I think
BreakIteration should inherit from StopIteration (thus retaining the
existing PEP 340 semantics if uncaught)::

Iteration
 |
 +- ContinueIteration
 |
 +- StopIteration
 |
 +- BreakIteration

I think no matter what it would be useful to be able to separate a break
from a stop sometimes, but there are many cases where they are the same
thing.

Tim Delaney
___
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 340: Breaking out.

2005-05-04 Thread Delaney, Timothy C (Timothy)
Aahz wrote:

> My standard workaround is using exceptions, but I'm not sure how that
> interacts with a block:
> 
> try:
> for name in filenames:
> with opened(name) as f:
> if f.read(2) == 0xFEB0:
> raise Found
> except Found:
> pass

For any sane block iterator, it will work as expected. However, an evil
block iterator could suppress the `Found` exception.

A sane block iterator should re-raise the original exception.

Tim Delaney
___
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 340 -- concept clarification

2005-05-04 Thread Delaney, Timothy C (Timothy)
Nick Coghlan wrote:

> Ah, someone else did post this idea first :)

I knew I was standing on the shoulders of others :)

> To deal with the generator issue, one option would be to follow up on
> Phillip's idea of a decorator to convert a generator (or perhaps any
> standard iterator) into a block iterator.
> 
> I think this would also do wonders for emphasising the difference
> between for loops and block statements.

I think if we are going to emphasise the difference, a decorator does
not go far enough. To use a decorator, this *must* be valid syntax::

def gen():
try:
yield
finally:
print 'Done!'

However, that generator cannot be properly used in a for-loop. So it's
only realistically valid with the decorator, and used in a block
statement (resource suite ;)

My feeling is that the above should be a SyntaxError, as it currently
is, and that a new keyword is needed which explicitly allows the above,
and creates an object conforming to the resource protocal (as I called
it).

Tim Delaney
___
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 340 -- concept clarification

2005-05-03 Thread Delaney, Timothy C (Timothy)
Delaney, Timothy C (Timothy) wrote:

> Guido van Rossum wrote:
> 
>> I'd like the block statement to be defined exclusively in terms of
>> __exit__() though.
> 
> 1. If an iterator declares __exit__, it cannot be used in a for-loop.
>For-loops do not guarantee resource cleanup.
> 
> 2. If an iterator does not declare __exit__, it cannot be used in a
> block-statement.
>Block-statements guarantee resource cleanup.

Now some thoughts have solidified in my mind ... I'd like to define some
terminology that may be useful.

resource protocol:
__next__
__exit__

Note: __iter__ is explicitly *not* required.

resource:
An object that conforms to the resource protocol.

resource generator:
A generator function that produces a resource.

resource usage statement/suite:
A suite that uses a resource.

With this conceptual framework, I think the following makes sense:

- Keyword 'resource' for defining a resource generator.
- Keyword 'use' for using a resource.

e.g.

::

resource locker (lock):
lock.acquire()
try:
yield
finally:
lock.release()

use locker(lock):
# do stuff

Tim Delaney
___
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 340 -- concept clarification

2005-05-03 Thread Delaney, Timothy C (Timothy)
Guido van Rossum wrote:

> I'd like the block statement to be defined exclusively in terms of
> __exit__() though.

This does actually suggest something to me (note - just a thought - no
real idea if it's got any merit).

Are there any use cases proposed for the block-statement (excluding the
for-loop) that do *not* involve resource cleanup (i.e. need an
__exit__)?

This could be the distinguishing feature between for-loops and
block-statements:

1. If an iterator declares __exit__, it cannot be used in a for-loop.
   For-loops do not guarantee resource cleanup.

2. If an iterator does not declare __exit__, it cannot be used in a
block-statement.
   Block-statements guarantee resource cleanup.

This gives separation of API (and thus purpose) whilst maintaining the
simplicity of the concept. Unfortunately, generators then become a pain
:( We would need additional syntax to declare that a generator was a
block generator.

OTOH, this may not be such a problem. Any generator that contains a
finally: around a yield automatically gets an __exit__, and any that
doesn't, doesn't. Although that feels *way* too magical to me (esp. in
light of my example below, which *doesn't* use finally). I'd prefer a
separate keyword for block generators. In that case, having finally:
around a yield would be a syntax error in a "normal" generator.

::

resource locking(lock):
lock.acquire()
try:
yield
finally:
lock.release()

block locking(myLock):
# Code here executes with myLock held.  The lock is
# guaranteed to be released when the block is left (even
# if via return or by an uncaught exception).

To use a (modified) example from another email::

class TestCase:

resource assertRaises (self, excClass):
try:
yield
except excClass:
return
else:
if hasattr(excClass, '__name__'): excName =
excClass.__name__
else: excName = str(excClass)
raise self.failureException, "%s is not raised" %
excName

block self.assertRaises(TypeError):
raise TypeError

Note that this *does* require cleanup, but without using a finally:
clause - the except: and else: are the cleanup code.

Tim Delaney
___
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 340 -- loose ends

2005-05-03 Thread Delaney, Timothy C (Timothy)
Another loose end (which can partially explain why I still thought
__next__ took an exception ;)

In "Specification: Generator Exit Handling"::

"When __next__() is called with an argument that is not None, the
yield-expression that it resumes will return the value attribute
of the argument."

I think this should read::

"When __next__() is called with an argument that is not None, the
yield-expression that it resumes will return the argument."

Tim Delaney
___
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 340 -- loose ends

2005-05-02 Thread Delaney, Timothy C (Timothy)
Guido van Rossum wrote:

> Oops. Read the most recent version of the PEP again. __next__()
> doesn't take an exception argument, it only takes a value. Maybe this
> removes your concern?

Actually, I misinterpreted it, assuming that the value passed in was an
exception instance because the previous versions worked that way. This
has been going on too long ;)

> Ah, here we see the other misconception (caused by not reading the
> most recent version of the PEP). __exit__() shouldn't call __next__()
> -- it should just raise the exception passed in unless it has
> something special to do.

Ah - I think this needs to be explained better. In particular, in the
specification of the __next__ and __exit__ methods it should state what
exceptions are expected to be raised under what circumstances - in
particular, that __exit__ is expected to raise the passed in exception
or StopIteration. This is only explained in the Generator Exception
Handling specification, but it's applicable to all iterators.

>> Finally, I think there is another loose end that hasn't been
>> addressed:: 
>> 
>> When __next__() is called with an argument that is not None, the
>> yield-expression that it resumes will return the value attribute
>> of the argument.  If it resumes a yield-statement, the value is
>> ignored (or should this be considered an error?).  When the
>> *initial* call to __next__() receives an argument that is not
>> None, the generator's execution is started normally; the
>> argument's value attribute is ignored (or should this be
>> considered an error?).  When __next__() is called without an
>> argument or with None as argument, and a yield-expression is
>> resumed, the yield-expression returns None.
> 
> Good catch.
> 
>> My opinion is that each of these should be an error.
> 
> Personally, I think not using the value passed into __next__() should
> not be an error; that's about the same as not using the value returned
> by a function you call.

Now that I understand that the parameter to __next__ is not an
exception, I agree.

> I agree that calling the initial __next__() of a generator with a
> non-None argument should be considered an error; this is likely caused
> by some kind of logic error; it can never happen when the generator is
> called by a block statement.

Cheers.

Tim Delaney
___
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 340 -- loose ends

2005-05-02 Thread Delaney, Timothy C (Timothy)
Guido van Rossum wrote:

> [Delaney, Timothy]
>> PEP 340 does not address "normal" iterators very well, but a
>> properly-constructed iterator will behave correctly.
> 
> This is by design.

Yep - I agree.

>> The PEP though is very generator-focussed.
> 
> Disagree. The PEP describes most everything (e.g. the block statement
> semantics) in terms of iterators, and then describes how the new APIs
> behave for generators.

Again, agree. What I meant is that there are no examples of how to
actually implement the correct semantics for a normal iterator. Doing it
right is non-trivial, especially with the __next__ and __exit__
interaction (see below).

>> The issues I see for "normal"
>> iterators (and that need to be addressed/stated in the PEP) are:
>> 
>> 1. No automatic handling of parameters passed to __next__ and
>>__exit__. In a generator, these will raise at the yield
>>-statement or -expression. A "normal" iterator will have
>>to take care of this manually. 
> 
> Not sure what you mean by this. If __next__() is defined, it is passed
> the parameter; if only next() is defined, a parameter (except None) is
> an error. That seems exactly right. Also, if __exit__() isn't defined,
> the exception is raised, which is a very sensible default behavior
> (and also what will happen to a generator that doesn't catch the
> exception).

What I meant is how the iterator is meant to handle the parameters
passed to each method. PEP 340 deals with this by stating that
exceptions will be raised at the next yield-statement or -expression. I
think we need an example though of how this would translate to a
"normal" iterator. Something along the lines of::

class iterator (object):

def next (self):
return self.__next__()

def __next__(self, arg=None):
value = None

if isinstance(arg, ContinueIteration):
value = arg.value
elif arg is not None:
raise arg

if value is None:
raise StopIteration

return value

def __exit__(self, type=None, value=None, traceback=None):
if (type is None) and (value is None) and (traceback is
None):
type, value, traceback = sys.exc_info()

if type is not None:
try:
raise type, value, traceback
except type, exc:
return self.__next__(exc)
 
   return self.__next__()

>> As another option, it might be worthwhile creating a base iterator
type
>> with "correct" semantics.

> Well, what would the "correct" semantics be? What would passing a
> parameter to a list iterator's __next__() method mean?

Sorry - I meant for user-defined iterators. And the correct semantics
would be something like the example above I think. Except that I think
most of it would need to be in a separate method (e.g. _next) for base
classes to call - then things would change to be something like::

class iterator (object):
...

def _next (self, arg):
if isinstance(arg, ContinueIteration):
return arg.value
elif arg is not None:
raise arg

def __next__(self, arg=None):
value = self._next(arg)

if value is None:
raise StopIteration

return value

...

Finally, I think there is another loose end that hasn't been addressed::

When __next__() is called with an argument that is not None, the
yield-expression that it resumes will return the value attribute
of the argument.  If it resumes a yield-statement, the value is
ignored (or should this be considered an error?).  When the
*initial* call to __next__() receives an argument that is not
None, the generator's execution is started normally; the
argument's value attribute is ignored (or should this be
considered an error?).  When __next__() is called without an
argument or with None as argument, and a yield-expression is
resumed, the yield-expression returns None.

My opinion is that each of these should be an error.

Tim Delaney
___
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 340 -- loose ends

2005-05-02 Thread Delaney, Timothy C (Timothy)
Phillip J. Eby wrote:

> Specifically, I propose that PEP 340 *not* allow the use of "normal"
> iterators.  Instead, the __next__ and __exit__ methods would be an
> unrelated protocol.  This would eliminate the need for a 'next()'
> builtin, 
> and avoid any confusion between today's iterators and a template
> function 
> for use with blocks.

PEP 340 does not address "normal" iterators very well, but a
properly-constructed iterator will behave correctly.

The PEP though is very generator-focussed. The issues I see for "normal"
iterators (and that need to be addressed/stated in the PEP) are:

1. No automatic handling of parameters passed to __next__ and
__exit__.
   In a generator, these will raise at the yield-statement or
-expression.
   A "normal" iterator will have to take care of this manually.

This could be an argument to only allow generator-iterators to be used
with PEP 340 semantics (i.e. continue , block), but I don't think
it's a very compelling one.

Although perhaps the initial implementation could be restricted to
generator-iterators. So if a for-loop used `continue ` it would
have a check (at the start of the for loop) that the iterator is a
generator-iterator. Likewise, a block-statement would always include
this check.

As another option, it might be worthwhile creating a base iterator type
with "correct" semantics.

Tim Delaney
___
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] @decoration of classes

2005-03-30 Thread Delaney, Timothy C (Timothy)
Nick Coghlan wrote:

># A decorator that does not alter its argument
>def register(callable):
>  # Register the callable somewhere
>  ...
>  return callable
> 
># Decorated factory function
>@register
>def factory():
>  pass
> 
># Post-decorated class
>class factory:
>  pass
>register(factory)
> 
># Metaclass
>class RegisteredType(type):
>  def __init__(self, name, bases, dict):
>super(self, RegisteredType).__init__(self, name, bases, dict)
>register(self)
> 
>class factory:
>  __metaclass__ = RegisteredType
> 
># Class decorator (not currently possible)
>@register
>class factory:
>  pass

class factory:

@register
def __call__(self):
pass

Just as an additional data point - obviously not applicable in all
cases.

Tim Delaney
___
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@python.org

2005-03-23 Thread Delaney, Timothy C (Timothy)
Rodrigo Dias Arruda Senra wrote:

> However, there are two other issues:
> 1) If a *graphical* application  dumps messages to the console,
>that might be disruptive to other console applications.
>IMVHO, a log file should be used instead. (strong argument)

Perhaps instead webbrowser.py should redirect to a (preferably
specified) log file. The detail is then still available, but hidden from
normal usage.

Tim Delaney
___
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] LinkedHashSet/LinkedHashMap equivalents

2005-03-09 Thread Delaney, Timothy C (Timothy)
Steven Bethard wrote:

> def filterdups(iterable):
>  seen = set()
>  for item in iterable:
>  if item not in seen:
>  seen.add(item)
>  yield item
> 
> Adding this to, say, itertools would cover all my use cases.  And as
> long as you don't have too many duplicates, filterdups as above should
> keep memory consumption down better.

Thinking about this further - memory usage would be almost identical. By
the time you completed the iterable, you would have built up exactly the
same set internally - although probably not as memory efficient since it
would be being built piecemeal. OTOH, an ordered set has a bit of extra
memory for maintaining the order, so it's going to be pretty close.

The only thing this gains you (and it's significant) is the ability to
work on any iterable lazily.

Tim Delaney
___
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] LinkedHashSet/LinkedHashMap equivalents

2005-03-09 Thread Delaney, Timothy C (Timothy)
Jeff Bauer wrote:

> I'm not specifically lobbying for its inclusion in
> stdlib, but I often find an ordered dict useful when I
> want both ordered and random access, e.g. situations:
> 
>- database table fields/attributes
>- drop down field selectors

Yep - these are also cases that are familiar to me - it's the type of
thing you don't think about until you actually need it.

> In both cases, I could get by with other techniques, but I
> would use stdlib ordered dicts if they were available.
> I also prefer the term "ordered dict" to LinkedHashXXX.

You may notice the subject is LinkedHashXXX *equivalents* ;) There is no
way I would ever propose adding them with those names.

OTOH, "ordered set" and "ordered dict" implies different things to
different people - usually "sorted" rather than "the order things were
put in". Perhaps "temporally-ordered" ;)

BTW, just to clarify the semantics:

Set: Items are iterated over in the order that they are added. Adding an
item that compares equal to one that is already in the set does not
replace the item already in the set, and does not change the iteration
order. Removing an item, then re-adding it moves the item to the end of
the iteration order.

Dict: Keys are iterated over in the order that they are added. Setting a
value using a key that compares equal to one already in the dict
replaces the value, but not the key, and does not change the iteration
order. Removing a key (and value) then re-adding it moves the key to the
end of the iteration order.

Tim Delaney
___
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] LinkedHashSet/LinkedHashMap equivalents

2005-03-08 Thread Delaney, Timothy C (Timothy)
Greg Ward wrote:

> I'll attach another approach to the same problem, an ordered
> dictionary object.  I believe the semantics of
> adding/readding/deleting keys is the same as java.util.LinkedHashMap
> -- certainly it seems the most sensible and easy-to-implement
> semantics. 

That's essentially the same approach I used - I didn't get around to
properly implementing a doubly-linked list between the keys - I just
maintained a list with the correct order. If I'm going to write a
Cookbook recipe though I should probably do it properly ...

Personally, I think it would be quite nice if all python dictionaries
had these semantics - it would be nice to be able to say that items will
be returned in the order they're inserted - but I wouldn't want to incur
the additional cost in such a fundamental data structure.

One thing I did notice - dict.__repr__ and dict.__str__ don't produce
strings in the iteration order of subclasses - they always use the
arbitrary dict iteration order. Is this intentional?

Tim Delaney
___
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] LinkedHashSet/LinkedHashMap equivalents

2005-03-08 Thread Delaney, Timothy C (Timothy)
The perennial "how do I remove duplicates from a list" topic came up on
c.l.py and in the discussion I mentioned the java 1.5 LinkedHashSet and
LinkedHashMap. I'd thought about proposing these before, but couldn't
think of where to put them. It was pointed out that the obvious place
would be the collections module.

For those who don't know, LinkedHashSet and LinkedHashMap are simply
hashed sets and maps that iterate in the order that the keys were added
to the set/map. I almost invariably use them for the above scenario -
removing duplicates without changing order.

Does anyone else think it would be worthwhile adding these to
collections, or should I just make a cookbook entry?

Cheers.

Tim Delaney
___
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] Getting rid of unbound methods: patch available

2005-01-18 Thread Delaney, Timothy C (Timothy)
Guido van Rossum wrote:

> [Timothy Delaney]
>> If im_func were set to the class where the function was defined, I
>> could definitely avoid the second part of the trawling (not sure
>> about the first yet, since I need to get at the function object).
> 
> Instead of waiting for unbound methods to change their functionality,
> just create a metaclass that sticks the attribute you want on the
> function objects.

Yep - that's one approach I've considered. I've also thought about
modifying the code objects, which would mean I could grab the base class
directly.

It's definitely not the most compelling use case in the world ;)

Tim Delaney
___
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] Getting rid of unbound methods: patch available

2005-01-17 Thread Delaney, Timothy C (Timothy)
Guido van Rossum wrote:

> Keeping im_class would be tricky -- the information isn't easily
> available when the function is defined, and adding it would require
> changing unrelated code that the patch so far didn't have to get near.
> Also, it would not be compatible -- the unbound method sets im_class
> to whichever class was used to retrieve the attribute, not the class
> in which the function was defined.

I actually do have a use case for im_class, but not in its current
incarnation. It would be useful if im_class was set (permanently) to the
class in which the function was defined.

My use case is my autosuper recipe. Currently I have to trawl through
the MRO, comparing code objects to find out which class I'm currently
in. Most annoyingly, I have to trawl *beyond* where I first find the
function, in case it's actually come from a base class (otherwise
infinite recursion can result ;)

If im_func were set to the class where the function was defined, I could
definitely avoid the second part of the trawling (not sure about the
first yet, since I need to get at the function object).

Cheers.

Tim Delaney
___
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: super() harmful?

2005-01-06 Thread Delaney, Timothy C (Timothy)
Guido van Rossum wrote:

>> and the cumbersome way in which you have to invoke super.
> 
> Given Python's dynamic nature I couldn't think of a way to make it
> less cumbersome. I see you tried (see below) and couldn't either. At
> this point I tend to say "put up or shut up."

Well, there's my autosuper recipe you've seen before:
http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/286195

which does basically what Philip descibes ...

>>> import autosuper
>>>
>>> class A (autosuper.autosuper):
... def test (self, a):
... print 'A.test: %s' % (a,)
...
>>> class B (A):
... def test (self, a):
... print 'B.test: %s' % (a,)
... self.super(a + 1)
...
>>> class C (A):
... def test (self, a):
... print 'C.test: %s' % (a,)
... self.super.test(a + 1)
...
>>> class D (B, C):
... def test (self, a):
... print 'D.test: %s' % (a,)
... self.super(a + 1)
...
>>> D().test(1)
D.test: 1
B.test: 2
C.test: 3
A.test: 4

It uses sys._getframe() of course ...

Tim Delaney
___
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] Out-of-date FAQs

2005-01-03 Thread Delaney, Timothy C (Timothy)
Aahz wrote:

> Yes.  Until last July, the company I work for was still using 1.5.2.
> Our current version is 2.2.  I think that the FAQ should be usable for
> anyone with a "reasonably current" version of Python, say at least two
> major versions.  IOW, answers should continue to work with 2.2 during
> the lifetime of 2.4.

That seems reasonable to me.

Tim Delaney
___
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] Out-of-date FAQs

2005-01-03 Thread Delaney, Timothy C (Timothy)
While grabbing the link to the copyright restrictions FAQ (for someone
on python-list) I noticed a few out-of-date FAQ entries - specifically,
"most stable version" and "Why doesn't list.sort() return the sorted
list?". Bug reports have been submitted (and acted on - Raymond, you
work too fast ;)

I think it's important that the FAQs be up-to-date with the latest
idioms, etc, so as I have the time available I intend to review all the
existing FAQs that I'm qualified for.

As a general rule, when an idiom has changed, do we want to state both
the 2.4 idiom as well as the 2.3 idiom? In the case of list.sort(), that
would mean having both:

for key in sorted(dict.iterkeys()):
...do whatever with dict[key]...

and

keys = dict.keys()
keys.sort()
for key in keys:
...do whatever with dict[key]...

Tim Delaney
___
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] MinGW And The other Py2.4 issue

2004-12-14 Thread Delaney, Timothy C (Timothy)
"Martin v. Löwis" wrote:

> Not at all. I'm talking about the release process, and prerequisites
> required in that process. This is worth mentioning because the list
> of prerequisites you need to perform a Python release is already quite
> long:

Ah - sorry - misinterpreted.

What is the size of the generated libpython24.a? Unfortunately, I don't happen 
to have binutils installed in my work cygwin (pulling it down now, but it's 
very slow ...) so I can't check myself (I've built the 2.3 one at home before 
...).

Tim Delaney
___
Python-Dev mailing list
[EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com


RE: [Python-Dev] MinGW And The other Py2.4 issue

2004-12-14 Thread Delaney, Timothy C (Timothy)
"Martin v. Löwis" wrote:

> Paul Moore wrote:
>> Thanks for your comments. Your support for the viability of building
>> extensions using mingw is important to me, so if you still have any
>> concerns, let me know and I will do my best to address them.
> 
> I understand that one still needs to build libpython24.a in order to
> use this process. As I have said, I'd happily ship that file with the
> 2.4.1 MSI, unless the release manager tells me that this would an
> unacceptable new feature, and as long as somebody provides a fully
> automatic build process integrated into msi.py; for that build
> process, 
> it is ok to assume that a cygwin installation is in c:\cygwin.

I think we should aim to support MSYS as well as Cygwin, but perhaps not for 
the first version where this goes in.

OTOH, is it really necessary to have either MSYS or Cygwin? MinGW32 works 
standalone - distutils should be able to just invoke it.

Tim Delaney
___
Python-Dev mailing list
[EMAIL PROTECTED]
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: The Other Py2.4 issue?

2004-12-12 Thread Delaney, Timothy C (Timothy)
Adam Bark wrote:

> Now this might sound a bit stupid but I've only been programming in
> python for about 6 months and before that about the same on VB. Anyway
> here goes, as python is built in C & C++ surely every piece of python
> code has a corresponding piece of C/C++ albeit more complex. So would
> it be possible to somehow make a program to convert the Python to C &
> C++ which can then be compiled with a C/C++ compiler.

Yes. And it would run at about the same speed as CPython.

The only way to significantly improve this is to remove much of the
dynamism of Python. As an example, I've been playing around with
Raymond's constant binding - making it do more aggressive binding (I'll
give an example later). By binding constants, I'm able to reduce the
runtimes for psyco-compiled versions of friendly code (lots of things
that can be converted into constant references) from around 2 seconds to
less than 0.001 seconds.

That's a very significant speedup. Unfortunately, it doesn't translate
as well into real-world code - or even benchmarks (parrotbench for
example gets a slight speedup but it's not overly significant).

As a quick example if the changes I'm playing with, 

def func()
docutils.parsers.rst.states.struct.__init__

Raymond's generates:

JUMP_FORWARD   0
LOAD_CONST(docutils)
LOAD_ATTR (parsers)
LOAD_ATTR (rst)
LOAD_ATTR (states)
LOAD_ATTR (struct)
LOAD_ATTR (__init__)

Mine generates

 0 JUMP_ABSOLUTE  15
 3 NOP
 4 NOP
 5 NOP
 6 NOP
 7 NOP
 8 NOP
 9 NOP
10 NOP
11 NOP
12 NOP
13 NOP
14 NOP
15 LOAD_CONST (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: 2.4 news reaches interesting places

2004-12-09 Thread Delaney, Timothy C (Timothy)
Michael Hudson wrote:

> Anthony's Australian, people expect this sort of thing from him :)

As another Australian, I think that "Making Python Not Suck" implies
that if you don't do extra things, Python Sucks.

This is not a good thing IMO.

"Making Python Suck Less" would be even worse.

How about "Python - You Can Have Your Cake And Eat It Too".

Tim Delaney
___
Python-Dev mailing list
[EMAIL PROTECTED]
http://mail.python.org/mailman/listinfo/python-dev
Unsubscribe: 
http://mail.python.org/mailman/options/python-dev/archive%40mail-archive.com