Re: [Python-Dev] Iterating over objects of unknown length

2007-09-26 Thread Oleg Broytmann
On Thu, Sep 27, 2007 at 01:33:47PM +1200, Greg Ewing wrote:
> Oleg Broytmann wrote:
> >if sqlQuery:
> >   for row in sqlQuery: ...
> >else:
> >   # no rows
> >
> >To prevent users from writing such code the class implements __nonzero__()
> >that always raises an exception.
> 
> I'm not sure I like that idea. It's common practice to write
> 'if x:' as a shorthand for 'if x is not None:' when it's known
> that x is an object that doesn't have a notion of emptiness.
> Another thing is that any code doing "if x" to test for
> emptiness is clearly expecting x to be a sequence, *not*
> an iterator, and you've violated the contract by passing
> it one. This is what you may be running into with the libraries
> you mention.

   In most cases the code in those libraries is, using the word of Mr. van
Rossum, "archaic". It was developed for old versions of Python (long before
Python has got the iterator protocol). I will file bug reports and patches
(I have filed one about logginig/__init__.py) to allow developers to either
fix the code or document the fact the code really requires a finite
sequence.
   Unfortunately now when my code no longer raises an exception it would be
harder to spot the buggy libraries.

> Generally I think it's a bad idea to try to protect people
> from themselves when doing so can interfere with legitimate
> usage.

   I agree. I admitted in mailing list it was my design mistake. The
offending __nonzero__ was removed from SVN today.

Oleg.
-- 
 Oleg Broytmannhttp://phd.pp.ru/[EMAIL PROTECTED]
   Programmers don't die, they just GOSUB without RETURN.
___
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] Iterating over objects of unknown length

2007-09-26 Thread Greg Ewing
Oleg Broytmann wrote:
> Hello!
> 
>(This seems like a "developing with Python" question and partially it is
> but please read on.)
> 
>I have a class that represents SQL queries. Instances of the class can
> be iterated over. ... users of
> the class sometimes write
> 
> if sqlQuery:
>for row in sqlQuery: ...
> else:
># no rows
> 
> To prevent users from writing such code the class implements __nonzero__()
> that always raises an exception.

I'm not sure I like that idea. It's common practice to write
'if x:' as a shorthand for 'if x is not None:' when it's known
that x is an object that doesn't have a notion of emptiness.
A __nonzero__ that always raises an exception just to spite
you interferes with that.

Another thing is that any code doing "if x" to test for
emptiness is clearly expecting x to be a sequence, *not*
an iterator, and you've violated the contract by passing
it one. This is what you may be running into with the libraries
you mention.

Generally I think it's a bad idea to try to protect people
from themselves when doing so can interfere with legitimate
usage.

-- 
Greg Ewing, Computer Science Dept, +--+
University of Canterbury,  | Carpe post meridiem! |
Christchurch, New Zealand  | (I'm not a morning person.)  |
[EMAIL PROTECTED]  +--+
___
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] Iterating over objects of unknown length

2007-09-26 Thread Oleg Broytmann
On Wed, Sep 26, 2007 at 09:29:10AM -0700, Guido van Rossum wrote:
> But I also fail to see why you would be so draconian as to disallow
> truth testing of a query altogether. Your query looks like an
> iterator. There are tons of other iterators in the language, library
> and 3rd party code, and it would be madness to try to fix all of them
> in the way you suggest just because some users don't get the concept
> of iterators.

   Seems me myself didn't get it:

On Wed, Sep 26, 2007 at 12:33:33PM -0400, Phillip J. Eby wrote:
> This isn't consistent with iterators; e.g.:
> 
> >>> x=iter([])
> >>> if x: print "yes"
> ...
> yes

On Wed, Sep 26, 2007 at 09:29:10AM -0700, Guido van Rossum wrote:
> So I'm for #1 *and* #2.

   I see now. Thank you!

Oleg.
-- 
 Oleg Broytmannhttp://phd.pp.ru/[EMAIL PROTECTED]
   Programmers don't die, they just GOSUB without RETURN.
___
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] Iterating over objects of unknown length

2007-09-26 Thread Phillip J. Eby
At 07:24 PM 9/26/2007 +0400, Oleg Broytmann wrote:
>Hello!
>
>(This seems like a "developing with Python" question and partially it is
>but please read on.)
>
>I have a class that represents SQL queries. Instances of the class can
>be iterated over. As an SQL query doesn't know in advance if it will
>produce any row the class doesn't implement __len__(). Moreover, users of
>the class sometimes write
>
>if sqlQuery:
>for row in sqlQuery: ...
>else:
># no rows

This isn't consistent with iterators; e.g.:

 >>> x=iter([])
 >>> if x: print "yes"
...
yes

ISTM that you should be returning "True" from __nonzero__, since you 
don't implement len().


>1. Should I consider this a bug in the logging module (and other libraries)
>and submit patches?
>2. Or should I stop raising exceptions in __nonzero__()?

#2 - Python objects should always be __nonzero__, unless they are 
empty containers, zeros, or otherwise specifically False.  It's 
reasonable for libraries to expect that truth-testing an object is always safe.

___
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] Iterating over objects of unknown length

2007-09-26 Thread Guido van Rossum
The logging code looks archaic: IMO it should be:

  if args and len(args) == 1 and isinstance(args[0], dict) and args[0]:

But I also fail to see why you would be so draconian as to disallow
truth testing of a query altogether. Your query looks like an
iterator. There are tons of other iterators in the language, library
and 3rd party code, and it would be madness to try to fix all of them
in the way you suggest just because some users don't get the concept
of iterators.

So I'm for #1 *and* #2.

--Guido

On 9/26/07, Oleg Broytmann <[EMAIL PROTECTED]> wrote:
> Hello!
>
>(This seems like a "developing with Python" question and partially it is
> but please read on.)
>
>I have a class that represents SQL queries. Instances of the class can
> be iterated over. As an SQL query doesn't know in advance if it will
> produce any row the class doesn't implement __len__(). Moreover, users of
> the class sometimes write
>
> if sqlQuery:
>for row in sqlQuery: ...
> else:
># no rows
>
> which is a bug (the query doesn't know if it's True or False; to find it
> out the user have to execute the query by trying to iterate over it). To
> prevent users from writing such code the class implements __nonzero__()
> that always raises an exception.
>Unfortunately, I found some libraries test the object in boolean context
> before iterating over it and that, of course, triggers the exception from
> __nonzero__().
>Even worse, some libraries test the object in boolean context regardless
> of iterating over it. For example, logging module (this is where my
> question becomes "developing for Python") triggers the exception in such
> simple case:
>
> logginig.debug("Query: %s", sqlQuery)
>
>Funny, the code
>
> logginig.debug("Query: %s, another: %s", sqlQuery, another_value)
>
>doesn't trigger the exception. This is due to the code in
> logginig/__init__.py:
>
> if args and (len(args) == 1) and args[0] and (type(args[0]) == 
> types.DictType):
> args = args[0]
>
> (class LogRecord, method __init__). "and args[0]" triggers the exception.
>
>My questions are:
>
> 1. Should I consider this a bug in the logging module (and other libraries)
>and submit patches?
> 2. Or should I stop raising exceptions in __nonzero__()?
>
>In this particular case with logging the fix is simple - do "and args[0]"
> after type check.
>
> Oleg.
> --
>  Oleg Broytmannhttp://phd.pp.ru/[EMAIL PROTECTED]
>Programmers don't die, they just GOSUB without RETURN.
> ___
> 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/guido%40python.org
>


-- 
--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


[Python-Dev] Iterating over objects of unknown length

2007-09-26 Thread Oleg Broytmann
Hello!

   (This seems like a "developing with Python" question and partially it is
but please read on.)

   I have a class that represents SQL queries. Instances of the class can
be iterated over. As an SQL query doesn't know in advance if it will
produce any row the class doesn't implement __len__(). Moreover, users of
the class sometimes write

if sqlQuery:
   for row in sqlQuery: ...
else:
   # no rows

which is a bug (the query doesn't know if it's True or False; to find it
out the user have to execute the query by trying to iterate over it). To
prevent users from writing such code the class implements __nonzero__()
that always raises an exception.
   Unfortunately, I found some libraries test the object in boolean context
before iterating over it and that, of course, triggers the exception from
__nonzero__().
   Even worse, some libraries test the object in boolean context regardless
of iterating over it. For example, logging module (this is where my
question becomes "developing for Python") triggers the exception in such
simple case:

logginig.debug("Query: %s", sqlQuery)

   Funny, the code

logginig.debug("Query: %s, another: %s", sqlQuery, another_value)

   doesn't trigger the exception. This is due to the code in
logginig/__init__.py:

if args and (len(args) == 1) and args[0] and (type(args[0]) == 
types.DictType):
args = args[0]

(class LogRecord, method __init__). "and args[0]" triggers the exception.

   My questions are:

1. Should I consider this a bug in the logging module (and other libraries)
   and submit patches?
2. Or should I stop raising exceptions in __nonzero__()?

   In this particular case with logging the fix is simple - do "and args[0]"
after type check.

Oleg.
-- 
 Oleg Broytmannhttp://phd.pp.ru/[EMAIL PROTECTED]
   Programmers don't die, they just GOSUB without RETURN.
___
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