Re: adding a simulation mode

2012-07-13 Thread andrea crotti
2012/7/13 Steven D'Aprano steve+comp.lang.pyt...@pearwood.info:

 Well of course it does. If copytree fails, the try block ends and
 execution skips straight to the except block, which runs, and then the
 program halts because there's nothing else to be done.

 That at least is my guess, based on the described symptoms.


Well I think that's what I was stupidly missing, I always had only one
possibly failing thing in a try/except block,
and I always gave for granted that it doesn't jump to the except block
on first error, but of course it makes
more sense if it does...

Thanks a lot
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-13 Thread Hans Mulder
On 13/07/12 04:16:53, Steven D'Aprano wrote:
 On Thu, 12 Jul 2012 16:37:42 +0100, andrea crotti wrote:
 
 2012/7/12 John Gordon gor...@panix.com:
 In mailman.2043.1342102625.4697.python-l...@python.org andrea crotti
 andrea.crott...@gmail.com writes:

 Well that's what I thought, but I can't find any explicit exit
 anywhere in shutil, so what's going on there?

 Try catching SystemExit specifically (it doesn't inherit from
 Exception, so except Exception won't catch it.)


 Ah yes that actually works, but I think is quite dodgy, why was it done
 like this?

It may be that the function you're calling found a problem that the
author thinks is so grave that they shouldn't give you an opportunity
to deal with it.

If that's the case, I would be inclined to think that they are wrong.

 Built-in exceptions SystemExit, KeyboardInterrupt and GeneratorExit 
 deliberately do not inherit from Exception since they are not meant to be 
 caught by catch-all try...except Exception clauses.
 
 You can see the exception hierarchy here:
 
 http://docs.python.org/library/exceptions.html#exception-hierarchy
 
 Please do NOT catch BaseException, since that is the wrong thing to do. 

I would agree if you had said in production code.

If you are investigating why a third-party function is stopping your
interpreter, then catching BaseException may tell you that the code
is raising the wrong kind of Exception.  Once you know what kind the
function is raising, you should catch only that particular excpetion
subclass.


 If you must catch SystemExit, KeyboardInterrupt, etc. they you should do 
 so as separate catch clauses:
 
 try:
 main()
 except SystemExit as e:
 print(e)  # see if we can find out who is raising this

If you want to find out who is raising the exception, you could
try this:

except SystemExit:
import traceback
traceback.print_exc()

That will print a complete stack trace.

If you only need to know what kind of exception you have,
you can do:

print(repr(e))

A simple print(e) will print str(e), which in the case of
SystemExit, is an empty string.  That's not very informative.

 except KeyboardInterrupt:
 print(Mwahahaha my pretty, you cannot cancel this!!!)
 print(...er, now what do I do?)
 except Exception:
 print(why am I catching exceptions I can't recover from?)


Hope this helps,

-- HansM
-- 
http://mail.python.org/mailman/listinfo/python-list


RE: adding a simulation mode

2012-07-13 Thread Prasad, Ramit
  Please do NOT catch BaseException, since that is the wrong thing to do.
 
 I would agree if you had said in production code.
 
 If you are investigating why a third-party function is stopping your
 interpreter, then catching BaseException may tell you that the code
 is raising the wrong kind of Exception.  Once you know what kind the
 function is raising, you should catch only that particular excpetion
 subclass.

I would say the opposite. In production code usually I want it
to recover, log as much information as I need (including sending
any notifications), and NOT just die.

In development, not catching the exception will give me a full 
trace back automatically. Why bother with trying to catch and 
print something when the interpreter will do it for me? Not
to mention that removes any hassle of trying to catch the
right exception or figuring out the best way to print it.
I suppose if there are arguments on the exception that were not
printed then I might want to catch it, but has been rare
in my experience.

Ramit

This email is confidential and subject to important disclaimers and
conditions including on offers for the purchase or sale of
securities, accuracy and completeness of information, viruses,
confidentiality, legal privilege, and legal entity disclaimers,
available at http://www.jpmorgan.com/pages/disclosures/email.  
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-13 Thread Chris Angelico
On Sat, Jul 14, 2012 at 3:08 AM, Prasad, Ramit
ramit.pra...@jpmorgan.com wrote:
 I would say the opposite. In production code usually I want it
 to recover, log as much information as I need (including sending
 any notifications), and NOT just die.

 In development, not catching the exception will give me a full
 trace back automatically.

Here's another take on the matter. In development, your script is your
execution unit, so you let the interpreter print out your tracebacks.
In production, there will usually be one, maybe two subunits (for
instance, a TCP-based server might have the socket connection as an
execution unit, and possibly a command parser inside that), and at the
top of that subunit, you have a broad exception handler that resets
that one unit (goes back and accepts another client, or waits for
another command). Otherwise, wide-scope exception handling is usually
a bad thing.

ChrisA
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread andrea crotti
One thing that I don't quite understand is why some calls even if I
catch the exception still makes the whole program quit.
For example this

try:
copytree('sjkdf', 'dsflkj')
Popen(['notfouhd'], shell=True)
except Exception as e:
print(here)


behaves differently from:

try:
Popen(['notfouhd'], shell=True)
copytree('sjkdf', 'dsflkj')
except Exception as e:
print(here)

because if copytree fails it quits anyway.
I also looked at the code but can't quite get why.. any idea?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread andrea crotti
One way instead that might actually work is this

def default_mock_action(func_name):
def _default_mock_action(*args, **kwargs):
print(running {} with args {} and {}.format(func_name, args, kwargs))

return _default_mock_action


def mock_fs_actions(to_run):
Take a function to run, and run it in an environment which
mocks all the possibly dangerous operations

side_effect = [
'copytree',
'copy',
]

acts = dict((s, default_mock_action(s)) for s in side_effect)

with patch('pytest.runner.commands.ShellCommand.run',
default_mock_action('run')):
with patch.multiple('shutil', **acts):
to_run()


So I can just pass the main function inside the mock like
mock_fs_actions(main)

and it seems to do the job, but I have to list manually all the things
to mock and I'm not sure is the best idea anyway..
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread John Gordon
In mailman.2039.1342099220.4697.python-l...@python.org andrea crotti 
andrea.crott...@gmail.com writes:

 try:
 copytree('sjkdf', 'dsflkj')
 Popen(['notfouhd'], shell=True)
 except Exception as e:
 print(here)

 behaves differently from:

 try:
 Popen(['notfouhd'], shell=True)
 copytree('sjkdf', 'dsflkj')
 except Exception as e:
 print(here)

 because if copytree fails it quits anyway.
 I also looked at the code but can't quite get why.. any idea?

copytree() could contain a call to sys.exit(), although that seems like
a rude thing to do.

-- 
John Gordon   A is for Amy, who fell down the stairs
gor...@panix.com  B is for Basil, assaulted by bears
-- Edward Gorey, The Gashlycrumb Tinies

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread andrea crotti
Well that's what I thought, but I can't find any explicit exit
anywhere in shutil, so what's going on there?
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread John Gordon
In mailman.2043.1342102625.4697.python-l...@python.org andrea crotti 
andrea.crott...@gmail.com writes:

 Well that's what I thought, but I can't find any explicit exit
 anywhere in shutil, so what's going on there?

Try catching SystemExit specifically (it doesn't inherit from Exception,
so except Exception won't catch it.)

-- 
John Gordon   A is for Amy, who fell down the stairs
gor...@panix.com  B is for Basil, assaulted by bears
-- Edward Gorey, The Gashlycrumb Tinies

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread andrea crotti
2012/7/12 John Gordon gor...@panix.com:
 In mailman.2043.1342102625.4697.python-l...@python.org andrea crotti 
 andrea.crott...@gmail.com writes:

 Well that's what I thought, but I can't find any explicit exit
 anywhere in shutil, so what's going on there?

 Try catching SystemExit specifically (it doesn't inherit from Exception,
 so except Exception won't catch it.)

 --

Ah yes that actually works, but I think is quite dodgy, why was it
done like this?
In shutil there is still no mention of SystemExit, and trying to raise
the single exceptions by and
doens't still make it exit, so I would still like to know how it is
possible just for curiosity..
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread Dieter Maurer
andrea crotti wrote at 2012-7-12 14:20 +0100:
One thing that I don't quite understand is why some calls even if I
catch the exception still makes the whole program quit.
For example this

try:
copytree('sjkdf', 'dsflkj')
Popen(['notfouhd'], shell=True)
except Exception as e:
print(here)


behaves differently from:

try:
Popen(['notfouhd'], shell=True)
copytree('sjkdf', 'dsflkj')
except Exception as e:
print(here)

because if copytree fails it quits anyway.
I also looked at the code but can't quite get why.. any idea?

There are ways to quit a program immediately without giving
exception handlers a chance to intervene -- though Python does
not make this easy.

Your code above should not do this. If it does, there is likely a bug.


You told us, that the two alternatives above behaved differently --
I expect 'behaved differently with respect to the printing of here'.
If you tell us, which alternative printed here and which did not,
we would be able to deduce which of the Popen or copytree
caused the immediate exit.

Popen might contain a call to os._exit (one of the ways to immediately
quit) -- though it should only call it in the forked child not in the
calling process. coyptree might under exceptional circumstances (extremely
deeply nested structures -- surely not for non-existent source and target)
cause a stack overflow (which, too, can lead to immediate death).


In addition, Popen and maybe even copytree may call platform
dependent functions. Thus, platform information could be relevant.

Under *nix, you should be able to get some information from
the exit code of a suddenly quiting process. It tells whether
the process died from a fatal signal (a stack overflow would
result in the fatal SIGSEGV) or whether it existed willingly with
an exit code.

--
Dieter
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread Steven D'Aprano
On Thu, 12 Jul 2012 15:17:03 +0100, andrea crotti wrote:

 Well that's what I thought, but I can't find any explicit exit anywhere
 in shutil, so what's going on there?

Hard to say, since you don't give any context to your question.

When replying to posts, please leave enough quoted to establish context. 
Neither email nor usenet are guaranteed delivery services, and they 
certainly don't guarantee to deliver messages in order. Assume that your 
readers may not have seen the message you are replying to, and you will 
probably get more and better responses.



-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread Steven D'Aprano
On Thu, 12 Jul 2012 16:37:42 +0100, andrea crotti wrote:

 2012/7/12 John Gordon gor...@panix.com:
 In mailman.2043.1342102625.4697.python-l...@python.org andrea crotti
 andrea.crott...@gmail.com writes:

 Well that's what I thought, but I can't find any explicit exit
 anywhere in shutil, so what's going on there?

 Try catching SystemExit specifically (it doesn't inherit from
 Exception, so except Exception won't catch it.)

 
 Ah yes that actually works, but I think is quite dodgy, why was it done
 like this?

Built-in exceptions SystemExit, KeyboardInterrupt and GeneratorExit 
deliberately do not inherit from Exception since they are not meant to be 
caught by catch-all try...except Exception clauses.

You can see the exception hierarchy here:

http://docs.python.org/library/exceptions.html#exception-hierarchy

Please do NOT catch BaseException, since that is the wrong thing to do. 
If you must catch SystemExit, KeyboardInterrupt, etc. they you should do 
so as separate catch clauses:

try:
main()
except SystemExit as e:
print(e)  # see if we can find out who is raising this
except KeyboardInterrupt:
print(Mwahahaha my pretty, you cannot cancel this!!!)
print(...er, now what do I do?)
except Exception:
print(why am I catching exceptions I can't recover from?)


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-12 Thread Steven D'Aprano
On Thu, 12 Jul 2012 14:20:18 +0100, andrea crotti wrote:

 One thing that I don't quite understand is why some calls even if I
 catch the exception still makes the whole program quit.

Without seeing your whole program, we can't possibly answer this. But by 
consulting my crystal ball, I bet you have something like this:

try:
do_stuff()  # run your program
except Exception as e:
# pointlessly catch exceptions I can't handle, which has the
# bonus of making debugging MUCH MUCH harder
print(here)
# end of file, nothing further to do


When do_stuff() fails, here gets printed, and then the program exits 
because there's nothing else to do.

Catching exceptions doesn't magically cause the code to continue from the 
point of the error. It doesn't work like that. Execution skips from where 
the error occurred to the except clause. Once the except clause has run, 
anything following the except clause runs, and then the program ends as 
normal.

If you haven't already done so, I recommend you go through the tutorial:

http://docs.python.org/py3k/tutorial/index.html

in particular the part about exception handling:

http://docs.python.org/py3k/tutorial/errors.html


 For example this
 
 try:
 copytree('sjkdf', 'dsflkj')
 Popen(['notfouhd'], shell=True)
 except Exception as e:
 print(here)

What is Popen and where is it from?

My first guess was os.popen, but that doesn't take a shell argument:

py os.popen(['ls', '-l'], shell=True)
Traceback (most recent call last):
  File stdin, line 1, in module
TypeError: popen() got an unexpected keyword argument 'shell'


 behaves differently from:
 
 try:
 Popen(['notfouhd'], shell=True)
 copytree('sjkdf', 'dsflkj')
 except Exception as e:
 print(here)
 
 because if copytree fails it quits anyway. 


Well of course it does. If copytree fails, the try block ends and 
execution skips straight to the except block, which runs, and then the 
program halts because there's nothing else to be done.

That at least is my guess, based on the described symptoms.




-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-05 Thread Dieter Maurer
andrea crotti andrea.crott...@gmail.com writes:

 I'm writing a program which has to interact with many external
 resources, at least:
 - mysql database
 - perforce
 - shared mounts
 - files on disk

 And the logic is quite complex, because there are many possible paths to
 follow depending on some other parameters.
 This program even needs to run on many virtual machines at the same time
 so the interaction is another thing I need to check...

 Now I successfully managed to mock the database with sqlalchemy and only
 the fields I actually need, but I now would like to simulate also
 everything else.

There is a paradigm called inversion of control which can be used
to handle those requirements.

With inversion of control, the components interact on the bases
of interfaces. The components themselves do not know each other, they
know only the interfaces they want to interact with. For the interaction
to really take place, a component asks a registry give me a component
satisfying this interface, gets it and uses the interface.

If you follow this paradigm, it is easy to switch components: just
register different alternatives for the interface at hand.


zope.interface and zope.component are python packages that
support this paradigm. Despite the zope in their name, they can be
used outside of Zope.

zope.interface models interfaces, while zope.component provides
so called utilities (e.g. database utility, filesystem utility, ...)
and adapters and the corresponding registries.


Of course, they contain only the infrastructure for the inversion of control
paradigm. Up to you to provide the implementation for the various
mocks.

-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-05 Thread andrea crotti
2012/7/5 Dieter Maurer die...@handshake.de:

 There is a paradigm called inversion of control which can be used
 to handle those requirements.

 With inversion of control, the components interact on the bases
 of interfaces. The components themselves do not know each other, they
 know only the interfaces they want to interact with. For the interaction
 to really take place, a component asks a registry give me a component
 satisfying this interface, gets it and uses the interface.

 If you follow this paradigm, it is easy to switch components: just
 register different alternatives for the interface at hand.


 zope.interface and zope.component are python packages that
 support this paradigm. Despite the zope in their name, they can be
 used outside of Zope.

 zope.interface models interfaces, while zope.component provides
 so called utilities (e.g. database utility, filesystem utility, ...)
 and adapters and the corresponding registries.


 Of course, they contain only the infrastructure for the inversion of control
 paradigm. Up to you to provide the implementation for the various
 mocks.



Thanks that's a good point, in short I could do something like:


class FSActions:
  @classmethod
  def copy_directories(cls, src, dest)
  raise NotImplementedError

  @classmethod
  

And then have different implementations of this interface.  This would
work, but I don't really like the idea of constructing interfaces that
provide only the few things I need.

Instead of being good APIs they might become just random
functionalities put together to make my life easier, and at that point
maybe just some clear mocking might be even better..
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-04 Thread Steven D'Aprano
On Wed, 04 Jul 2012 10:42:56 +0100, andrea crotti wrote:

 I'm writing a program which has to interact with many external
 resources, at least:
 - mysql database
 - perforce
 - shared mounts
 - files on disk
 
 And the logic is quite complex, because there are many possible paths to
 follow depending on some other parameters. This program even needs to
 run on many virtual machines at the same time so the interaction is
 another thing I need to check...
 
 Now I successfully managed to mock the database with sqlalchemy and only
 the fields I actually need, but I now would like to simulate also
 everything else.
 
 I would like for example that if I simulate I can pass a fake database,
 a fake configuration and get the log of what exactly would happen.  But
 I'm not sure how to implement it now..  One possibility would be to have
 a global variable (PRETEND_ONLY = False) that if set should be checked
 before every potentially system-dependent command.

I think a better way would be to use a mock database, etc. For each thing 
which you want to simulate, create a class that has the same interface 
but a simulated implementation.

Then, have your code accept the thing as an argument.

E.g. instead of having a hard-coded database connection, allow the 
database connection to be set (perhaps as an argument, perhaps as a 
config option, etc.).

There are libraries to help with mocks, e.g.:

http://garybernhardt.github.com/python-mock-comparison/
 

 For example
 
 copytree(src, dest) becomes:
 if not PRETEND_ONLY:
 copytree(src, dest)

Ewww :(

Mocking the file system is probably the hardest part, because you 
generally don't have a FileSystem object available to be replaced. In 
effect, your program has one giant global variable, the file system. 
Worse, it's not even a named variable, it's hard-coded everywhere you use 
it.

I don't know of any good solution for that. I've often thought about it, 
but don't have an answer.

I suppose you could monkey-patch a bunch of stuff:

if ONLY_PRETEND:
 open = my_mock_open
 copytree = my_mock_copytree
 # etc. 
main()  # run your application



but that would also be painful.


-- 
Steven
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-04 Thread andrea crotti
2012/7/4 Steven D'Aprano steve+comp.lang.pyt...@pearwood.info:

 Then, have your code accept the thing as an argument.

 E.g. instead of having a hard-coded database connection, allow the
 database connection to be set (perhaps as an argument, perhaps as a
 config option, etc.).

 There are libraries to help with mocks, e.g.:

 http://garybernhardt.github.com/python-mock-comparison/

Ah yes this part is already done, I pass an object to the entry point
of the program which represents the database connection, which looks
like this:

class MockMysqlEngine(MySqlEngine):
# TODO: make the engine more generic would avoid this dirty hack
def __init__(self, *args, **kwargs):
# self.engine =
create_engine('sqlite:home/andrea/testdb.sqlite', echo=True)
self.engine = create_engine('sqlite://', echo=True)
self.meta = MetaData(bind=self.engine)
self.session_maker = sessionmaker(bind=self.engine)


Now I populate statically the schema and populate with some test data
too, but I'm also implementing a weay to just pass some CSV files so
that other people can easily write some test cases with some other
possible database configurations.

(And I use mock for a few other things)




 For example

 copytree(src, dest) becomes:
 if not PRETEND_ONLY:
 copytree(src, dest)

 Ewww :(

 Mocking the file system is probably the hardest part, because you
 generally don't have a FileSystem object available to be replaced. In
 effect, your program has one giant global variable, the file system.
 Worse, it's not even a named variable, it's hard-coded everywhere you use
 it.

 I don't know of any good solution for that. I've often thought about it,
 but don't have an answer.

 I suppose you could monkey-patch a bunch of stuff:

 if ONLY_PRETEND:
  open = my_mock_open
  copytree = my_mock_copytree
  # etc.
 main()  # run your application



 but that would also be painful.


Yes there is no easy solution apparently..  But I'm also playing
around with vagrant and virtual machine generations, suppose I'm able
to really control what will be on the machine at time X, creating it
on demand with what I need, it might be a good way to solve my
problems (a bit overkill and slow maybe though).

I'll try the sys.excepthook trick first, any error should give me an
exception, so if I catch them all I think it might work already..
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-04 Thread andrea crotti
 Yes there is no easy solution apparently..  But I'm also playing
 around with vagrant and virtual machine generations, suppose I'm able
 to really control what will be on the machine at time X, creating it
 on demand with what I need, it might be a good way to solve my
 problems (a bit overkill and slow maybe though).

 I'll try the sys.excepthook trick first, any error should give me an
 exception, so if I catch them all I think it might work already..


I actually thought that the sys.excepthook would be easy but it's not
so trivial apparently:
This simple sample never reaches the print(here), because even if
the exception is catched it still quits with return code=1.

I also tried to catch the signal but same result, how do I make it
continue and just don't complain?

The other option if of course to do a big try/except, but I would
prefer the excepthook solution..


import sys
from shutil import copy

def my_except_hook(etype, value, tb):
print(got an exception of type, etype)


if __name__ == '__main__':
sys.excepthook = my_except_hook
copy('sdflsdk')
print(here)
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-04 Thread Mike C. Fletcher

On 12-07-04 05:42 AM, andrea crotti wrote:
...

copytree(src, dest) becomes:
if not PRETEND_ONLY:
 copytree(src, dest)

import globalsub, unittest

class MyTest( unittest.TestCase ):
def setUp( self ):
globalsub.subs( shutil.copytree )
def tearDown( self ):
globalsub.restore( shutil.copytree )

You can also pass a function to subs like so:

def setUp( self ):
self.copied_trees = []
def fake_copytree( src, dest ):
assert os.path.exists( src )
self.copied_trees.append( (src, dest ))
return dest # or whatever the thing should return
globalsub.subs( shutil.copytree, fake_copytree )

$ pip install globalsub

HTH,
Mike

--

  Mike C. Fletcher
  Designer, VR Plumber, Coder
  http://www.vrplumber.com
  http://blog.vrplumber.com

--
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-04 Thread Devin Jeanpierre
For what it's worth, this is the reason that Allen Short wrote Exocet.

 This way, you can test your code without having to resort to sys.modules
 hackery, and you can better factor your applications by separating
 configuration and environment concerns from the rest of your code.

See:

- http://washort.twistedmatrix.com/2011/01/introducing-exocet.html
- http://washort.twistedmatrix.com/2011/03/exocet-second-look.html

-- Devin
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: adding a simulation mode

2012-07-04 Thread Paul Rubin
andrea crotti andrea.crott...@gmail.com writes:
 copytree(src, dest) becomes:
 if not PRETEND_ONLY:
 copytree(src, dest)

 But I don't like it too much because I would have to add a lot of
 garbage around..

I've had good results writing the module under test in the style of a
java applet, i.e. one of its args is a class instance representing the
outside world, and ALL interaction that you might want to simulate is
done through this object:

   def your_prog(parent):
  conn = parent.db.make_connection(...)
  blah = parent.copytree(...)

Then you make real and mock versions of the external interface, and
pass in an appropriate instance.
-- 
http://mail.python.org/mailman/listinfo/python-list