[Python-ideas] Re: Compound with .. else statement

2020-09-09 Thread axelheider
Hi,

I was just about to make exactly the suggestion. Seem like a nice idea to have 
this, because it simplifies error handling a lot. 

Axel
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/3U3FYBBFB4YCWIVG47NZAD4UJ66OHGYI/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-04-03 Thread Jimmy Thrasibule
> but we don't need special syntax for "else" on a for or while loop (or try 
> block) either, you could always set a sentinel for those too.
> which to me is a case for adding else to a "with" block as well, for all the 
> same reasons it's there for the other block construct.

That's part of my opinion too, afaik, only `with` is currently missing
an `else` part.

> Though I don't think I'd advocate it in this case, as the Exception is not 
> really a clear part of the context manger API, like "break" is
> to the loops.

Well part of the __exit__ documentation, you can read the following:


Returning a true value from this method will cause the with
statement to suppress the exception and continue execution with the
statement immediately following the with statement. Otherwise the
exception continues propagating after this method has finished
executing.


So exceptions are quite part of the context manager API. Based on that
I actually created a context manager using this property:


class savepoint(object):

def __init__(self, tm):
self._sp = None
self._tm = tm


def __enter__(self) -> bool:
"""Save the current state of the transaction."""
try:
self._sp = self._tm.savepoint()
except TypeError:
return False
else:
return self._sp.valid


def __exit__(self, exc_type, exc_val: ty.Any, exc_tb):
"""Save the sub-transaction or roll it back in case an
error occurred."""
if exc_type is not None and issubclass(exc_type, DatabaseError):
self._sp.rollback()
return False
elif exc_type is not None:
raise exc_type(exc_val)
return True


The issue is that I have to enclose usage of the manager into a try/catch block:


try:
with savepoint(request.tm) as sp:
if not sp:
raise TypeError('Unsupported database.')

url = insert_url(request.db, u_url)
request.db.flush()
except IntegrityError:
url = lookup_url(request.db, u_url)


Having with/else I could do the following instead:


with savepoint(request.tm) as sp:
if not sp:
raise TypeError('Unsupported database.')

url = insert_url(request.db, u_url)
request.db.flush()
else:
url = lookup_url(request.db, u_url)


I therefore save some lines and indentations.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/PILLQVANNANGZ3P7G3ZTT7LAHKFE35K3/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-31 Thread Christopher Barker
On Tue, Mar 31, 2020 at 2:41 AM Serhiy Storchaka 
wrote:

> 31.03.20 01:32, Christopher Barker пише:
> > In case Serhiy's answer wasn't clear: context managers can be written to
> > handle exceptions (within their context) in any way you see fit.
> >
> > that is: the method:
> > |
> > |
> > |__exit__(||self||, exc_type, exc_value, exc_traceback):|
> >
> > get the exception, and information about it, of one is raised, so you
> > can handle it anyway you want.
>


> Actually I meant the opposite.


I think I was thrown by the use of the example "my_context" -- that is, if
you are writing a conrtect manger, you can handle exceptions any way you
like. If you are using an existing one, then, yes:


> the context manager does not silence a raised exception, so control flow
> is never passed to the statement past the with block if an exception is
> raised inside the with block.
>


>  was_not_raised = False
>  with my_context():
>do_something_sensitive()
>was_not_raised = True
>  if was_not_raised:
>  print("We're all safe.")
>
> You do not need a special syntax for this.


but we don't need special syntax for "else" on a for or while loop (or try
block) either, you could always set a sentinel for those too.

which to me is a case for adding else to a "with" block as well, for all
the same reasons it's there for the other block construct.

Though I don't think I'd advocate it in this case, as the Exception is not
really a clear part of the context manger API, like "break" is to the loops.

-CHB


-- 
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/4VLKOFTNDU3NPDIASCFHAS42PVU3XJX6/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-31 Thread Andrew Barnert via Python-ideas
On Mar 31, 2020, at 03:06, Jimmy Thrasibule  wrote:
> 
> 
>> 
>> But if you use a context manager which silences the exception, like
>> contextlib.suppress() or unittest.TestCase.assertRaises(), it is easy to
>> do too.
>> 
>> was_not_raised = False
>> with my_context():
>>   do_something_sensitive()
>>   was_not_raised = True
>> if was_not_raised:
>> print("We're all safe.")
> 
> That is indeed a way to workaround my use case. I do still find a
> with/else more elegant.

It might help your proposal to just show a small concrete and realistic example 
of how this workaround parallels the workaround for not having for/else, and 
how your proposed change would let you improve your code’s readability in 
exactly the same way as for/else. At least for me, it’s always been easier to 
show a newcomer to Python the point of for/else with a nice example than to try 
to explain the semantics and why they’re useful, and I assume the same would be 
true here.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/C5ATRBHHKOIOFIWET2J7ONGOJGK7VGBA/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-31 Thread Jimmy Thrasibule
> But if you use a context manager which silences the exception, like
> contextlib.suppress() or unittest.TestCase.assertRaises(), it is easy to
> do too.
>
>  was_not_raised = False
>  with my_context():
>do_something_sensitive()
>was_not_raised = True
>  if was_not_raised:
>  print("We're all safe.")

That is indeed a way to workaround my use case. I do still find a
with/else more elegant.
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/TO7ZCRVTPKSUL5EJ76F2IOMGUBTYLA33/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-31 Thread Serhiy Storchaka

31.03.20 01:32, Christopher Barker пише:
In case Serhiy's answer wasn't clear: context managers can be written to 
handle exceptions (within their context) in any way you see fit.


that is: the method:
|
|
|__exit__(||self||, exc_type, exc_value, exc_traceback):|

get the exception, and information about it, of one is raised, so you 
can handle it anyway you want.


Actually I meant the opposite. Sorry for being unclear. In normal case 
the context manager does not silence a raised exception, so control flow 
is never passed to the statement past the with block if an exception is 
raised inside the with block.


But if you use a context manager which silences the exception, like 
contextlib.suppress() or unittest.TestCase.assertRaises(), it is easy to 
do too.


was_not_raised = False
with my_context():
  do_something_sensitive()
  was_not_raised = True
if was_not_raised:
print("We're all safe.")

You do not need a special syntax for this. was_not_raised will never be 
set to True if do_something_sensitive() raises an exception.

___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/ERCV4NY5MHHXVZMSFZDISRG3OKIFRLOC/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-30 Thread Jimmy Thrasibule
>
> Perhaps you could use try/finally:
>
> try:
> prepare()
> do_something_sensitive()
> finally:
> cleanup()
>

Well I actually would like to run the else block in case an exception did
occurred.

Let me provide an example from my use case which is the management of a
database transaction:


with savepoint(transaction_manager):
# Let's try to add into the database with some constraints.
obj = db.add(data)
db.flush()
else:
# Object already in database.
obj = db.get(data)


With the following context manager:


class savepoint(object):
def __init__(self):
self._sp = None

def __enter__(self, tm):
self._sp = tm.savepoint()

def __exit__(self, exc_ty, exc_val, tb):
if exc_ty is not None and issubclass(ecx_ty, IntegrityError):
self._sp.rollback()
# We have an exception, execute else block.
return False

# All good, we commit our transaction.
self._sp.commit()
return True


I find it quite a pretty, try and fail back way that I can easily replicate
in my code without having to prepare and clean up each time with a
try/catch.

>
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/V5FHTPRRHQBKMLFPCRLBHTRQGEB6WTMB/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-30 Thread Christopher Barker
On Mon, Mar 30, 2020 at 3:19 PM Serhiy Storchaka 
wrote:

> 31.03.20 00:27, Jimmy Thrasibule пише:
> > In my situation, I would like to mix the `with` statement with `else`.
> > In this case I would like that if no exception is raised within the
> > `with` to run the `else` part.
>
> It is easy. You do not need "else".
>
> with my_context():
>   do_something_sensitive()
> print("We're all safe.")


In case Serhiy's answer wasn't clear: context managers can be written to
handle exceptions (within their context) in any way you see fit.

that is: the method:

__exit__(self, exc_type, exc_value, exc_traceback):

get the exception, and information about it, of one is raised, so you can
handle it anyway you want.

-CHB



> ___
> Python-ideas mailing list -- python-ideas@python.org
> To unsubscribe send an email to python-ideas-le...@python.org
> https://mail.python.org/mailman3/lists/python-ideas.python.org/
> Message archived at
> https://mail.python.org/archives/list/python-ideas@python.org/message/M7HVLCGQ6REMHKGZVZPIYTJGLN6WKN5F/
> Code of Conduct: http://python.org/psf/codeofconduct/
>


-- 
Christopher Barker, PhD

Python Language Consulting
  - Teaching
  - Scientific Software Development
  - Desktop GUI and Web Development
  - wxPython, numpy, scipy, Cython
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/7SXSGIENYXWKWTJFC7LELWT3XVH3EUOV/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-30 Thread Serhiy Storchaka

31.03.20 00:27, Jimmy Thrasibule пише:

In my situation, I would like to mix the `with` statement with `else`.
In this case I would like that if no exception is raised within the
`with` to run the `else` part.


It is easy. You do not need "else".

with my_context():
 do_something_sensitive()
print("We're all safe.")
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/M7HVLCGQ6REMHKGZVZPIYTJGLN6WKN5F/
Code of Conduct: http://python.org/psf/codeofconduct/


[Python-ideas] Re: Compound with .. else statement

2020-03-30 Thread Dan Sommers
On Mon, 30 Mar 2020 23:27:19 +0200
Jimmy Thrasibule  wrote:

> Now imagine that in my `try .. except` block I have some heavy setup
> to do before `do_something_sensitive()` and some heavy cleanup when
> the exception occurs.

> I'd like my context manager to do the preparation work, execute the
> body, and cleanup. Or execute my else block only if there is no
> exception.

> Is there already a way to accomplish this in Python or can this be a
> nice to have?

Perhaps you could use try/finally:

try:
prepare()
do_something_sensitive()
finally:
cleanup()

Whether the call to prepare goes inside or outside the try block depends
on many things, mostly its coupling to the cleanup procedure (e.g., do
they need to share objects? is cleanup idempotennt?).

HTH,
Dan

-- 
“Atoms are not things.” – Werner Heisenberg
Dan Sommers, http://www.tombstonezero.net/dan
___
Python-ideas mailing list -- python-ideas@python.org
To unsubscribe send an email to python-ideas-le...@python.org
https://mail.python.org/mailman3/lists/python-ideas.python.org/
Message archived at 
https://mail.python.org/archives/list/python-ideas@python.org/message/DGUP3WAOVLVC74TIOCVTMKMZKORTTON3/
Code of Conduct: http://python.org/psf/codeofconduct/