Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-08-11 Thread Neil Girdhar


On Monday, July 30, 2018 at 3:55:25 PM UTC-4, Kyle Lahnakoski wrote:
>
> Rudy,
>
> I think your proposal may be very specific to iterable context managers;
>

I don't think his proposal is specific to iterable context managers.  You 
can have a with clause that is used in a following for clause. 

in which case, make a method that makes that assumption:
>
> > def iter_with(obj):
> > with obj as context:
> > yield from context
>
> and use it
>
> > g = (
> > f.read()
> > for fn in filenames
> > for f in iter_with(open(fn))
> > )
>
> On 2018-07-30 15:15, Rudy Matela wrote:
> > Hello,
> >
> > Do you think it would be nice to allow with statements inside genexps or
> > list comprehensions?  The functions __enter__ and __exit__ would be
> > automatically called as iterables are traversed.  I am thinking of
> > drafting a PEP about this.  Examples:
> >
> >
> > This 
> >
> > g = (f.read() for fn in filenames with open(fn) as f)
> >
> > would be equivalent to the following use of a generator function:
> >
> > def __gen():
> > for fn in filenames:
> > with open(fn) as f:
> > yield f.read()
> > g = __gen()
> >
> >
> > This
> >
> > list = [f.read() for fn in filenames with open(fn) as f]
> >
> > would be equivalent to the following:
> >
> > list = []
> > for fn in filenames:
> > with open(fn) as f:
> > list.append(f.read())
> >
> > --
> > Rudy
> > ___
> > Python-ideas mailing list
> > python...@python.org 
> > https://mail.python.org/mailman/listinfo/python-ideas
> > Code of Conduct: http://python.org/psf/codeofconduct/
>
> ___
> Python-ideas mailing list
> python...@python.org 
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
>
>___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-08-08 Thread Thomas Jollans
On 30/07/18 21:15, Rudy Matela wrote:
> Hello,
> 
> Do you think it would be nice to allow with statements inside genexps or
> list comprehensions?  The functions __enter__ and __exit__ would be
> automatically called as iterables are traversed.  I am thinking of
> drafting a PEP about this.  Examples:
> 
> 
> This 
> 
>   g = (f.read() for fn in filenames with open(fn) as f)
> 
> would be equivalent to the following use of a generator function:
> 
>   def __gen():
>   for fn in filenames:
>   with open(fn) as f:
>   yield f.read()
>   g = __gen()


To sail around Oscar's concern, this should rather be

def __gen():
for fn in filenames:
with open(fn) as f:
_v = f.read()
yield _v

But in this case I think it'd be clearer to make it an expression rather
than a generator expression term:

g = (f.read() with open(fn) as f for fn in filenames)

where

_ = f.read() with open(fn) as f

is equivalent to

with open(fn) as f:
_ = f.read()

Currently possibly (if silly) alternative:

from functools import wraps

class with_one_use:
def __init__(self, context):
self.__context = context

def __getattr__(self, name):
exc1 = False
obj = self.__context.__enter__()
try:
temp = getattr(obj, name)
except:
exc1 = True
if not self.__context.__exit__(*sys.exc_info()):
raise
else:
if callable(temp):
@wraps(temp)
def f(*args, **kwargs):
exc2 = False
try:
return temp(*args, **kwargs)
except:
exc2 = True
if not self.__context.__exit__(*sys.exc_info()):
raise
finally:
if not exc2:
self.__context.__exit__(None, None, None)
exc1 = True
return f
else:
return temp
finally:
if not exc1:
self.__context.__exit__(None, None, None)


g = (with_one_use(open(fn)).read() for fn in filenames)


-- Thomas

> 
> 
> This
> 
>   list = [f.read() for fn in filenames with open(fn) as f]
> 
> would be equivalent to the following:
> 
>   list = []
>   for fn in filenames:
>   with open(fn) as f:
>   list.append(f.read())
> 
> --
> Rudy
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/
> 

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-07-31 Thread Serhiy Storchaka

31.07.18 00:26, Oscar Benjamin пише:

On 30 July 2018 at 20:15, Rudy Matela  wrote:
Yielding from a with block should be discouraged rather than given
special syntax. There is essentially a contradiction between the
meaning/purpose of yield (suspend indefinitely) and with (definitely
call __exit__).

If I partially iterate over g as in

 for line in g:
 break

then at this point g is suspended and f.__exit__ has not been called,
so the file is not closed. I may choose to iterate over g later or
not, so it has to remain in suspension just in case. In practice if
you do this in CPython then f.__exit__ will *probably* be invoked
indirectly by g.__del__ if/when the gc collects g. This defeats the
main point of using with-open though which is to avoid depending on
the gc for closing files.


Concur with Oscar.

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-07-31 Thread Rhodri James

On 30/07/18 20:15, Rudy Matela wrote:

Hello,

Do you think it would be nice to allow with statements inside genexps or
list comprehensions?  The functions __enter__ and __exit__ would be
automatically called as iterables are traversed.  I am thinking of
drafting a PEP about this.  Examples:


I was worried until I twigged that you meant adding a clause rather than 
a statement per se.  How does this interact with the other clauses in a 
comprehension?  I'm thinking of monstrosities like:


g = (f.read() for fn in filenames if fn.endswith(".txt") with open(fn) 
as f for filenames in get_directory_listing(dir) if .)


--
Rhodri James *-* Kynesim Ltd
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-07-30 Thread Oscar Benjamin
On 30 July 2018 at 20:15, Rudy Matela  wrote:
> Hello,

Hi Rudy,

> Do you think it would be nice to allow with statements inside genexps or
> list comprehensions?  The functions __enter__ and __exit__ would be
> automatically called as iterables are traversed.  I am thinking of
> drafting a PEP about this.  Examples:
>
>
> This
>
> g = (f.read() for fn in filenames with open(fn) as f)
>
> would be equivalent to the following use of a generator function:
>
> def __gen():
> for fn in filenames:
> with open(fn) as f:
> yield f.read()
> g = __gen()

Yielding from a with block should be discouraged rather than given
special syntax. There is essentially a contradiction between the
meaning/purpose of yield (suspend indefinitely) and with (definitely
call __exit__).

If I partially iterate over g as in

for line in g:
break

then at this point g is suspended and f.__exit__ has not been called,
so the file is not closed. I may choose to iterate over g later or
not, so it has to remain in suspension just in case. In practice if
you do this in CPython then f.__exit__ will *probably* be invoked
indirectly by g.__del__ if/when the gc collects g. This defeats the
main point of using with-open though which is to avoid depending on
the gc for closing files.

--
Oscar
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


Re: [Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-07-30 Thread Kyle Lahnakoski
Rudy,

I think your proposal may be very specific to iterable context managers;
in which case, make a method that makes that assumption:

> def iter_with(obj):
> with obj as context:
> yield from context

and use it

> g = (
> f.read()
> for fn in filenames
> for f in iter_with(open(fn))
> )

On 2018-07-30 15:15, Rudy Matela wrote:
> Hello,
>
> Do you think it would be nice to allow with statements inside genexps or
> list comprehensions?  The functions __enter__ and __exit__ would be
> automatically called as iterables are traversed.  I am thinking of
> drafting a PEP about this.  Examples:
>
>
> This 
>
>   g = (f.read() for fn in filenames with open(fn) as f)
>
> would be equivalent to the following use of a generator function:
>
>   def __gen():
>   for fn in filenames:
>   with open(fn) as f:
>   yield f.read()
>   g = __gen()
>
>
> This
>
>   list = [f.read() for fn in filenames with open(fn) as f]
>
> would be equivalent to the following:
>
>   list = []
>   for fn in filenames:
>   with open(fn) as f:
>   list.append(f.read())
>
> --
> Rudy
> ___
> Python-ideas mailing list
> Python-ideas@python.org
> https://mail.python.org/mailman/listinfo/python-ideas
> Code of Conduct: http://python.org/psf/codeofconduct/

___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Is this PEP-able? "with" statement inside genexps / list comprehensions

2018-07-30 Thread Rudy Matela
Hello,

Do you think it would be nice to allow with statements inside genexps or
list comprehensions?  The functions __enter__ and __exit__ would be
automatically called as iterables are traversed.  I am thinking of
drafting a PEP about this.  Examples:


This 

g = (f.read() for fn in filenames with open(fn) as f)

would be equivalent to the following use of a generator function:

def __gen():
for fn in filenames:
with open(fn) as f:
yield f.read()
g = __gen()


This

list = [f.read() for fn in filenames with open(fn) as f]

would be equivalent to the following:

list = []
for fn in filenames:
with open(fn) as f:
list.append(f.read())

--
Rudy
___
Python-ideas mailing list
Python-ideas@python.org
https://mail.python.org/mailman/listinfo/python-ideas
Code of Conduct: http://python.org/psf/codeofconduct/