473,473 Members | 1,733 Online
Bytes | Software Development & Data Engineering Community
Create Post

Home Posts Topics Members FAQ

doctest environment question

I'm not making progress with the following and would appreciate any
help.

Here's an interpreted Python session.
>>import sys
def f(): pass
....
>>this_module = sys.modules[__name__]
delattr(this_module, 'f')
f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined

Suppose I want to doctest this behaviour. I cut and paste the above
into a file "test.txt" then run:

python -c "import doctest; doctest.testfile('test.txt')"

This gives me unexpected test failures:

python -c "import doctest; doctest.testfile('test.txt')"
************************************************** ********************
File "test.txt", line 5, in test.txt
Failed example:
delattr(this_module, 'f')
Exception raised:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/doctest.py", line 1212, in __run
compileflags, 1) in test.globs
File "<doctest test.txt[3]>", line 1, in <module>
delattr(this_module, 'f')
AttributeError: f
************************************************** ********************
File "test.txt", line 6, in test.txt
Failed example:
f()
Expected:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined
Got nothing
************************************************** ********************
1 items had failures:
2 of 5 in test.txt
***Test Failed*** 2 failures.

May 21 '07 #1
12 2097
th**********@gmail.com wrote:
I'm not making progress with the following and would appreciate any
help.

Here's an interpreted Python session.
>>>import sys
def f(): pass
...
>>>this_module = sys.modules[__name__]
delattr(this_module, 'f')
f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined

Suppose I want to doctest this behaviour. I cut and paste the above
into a file "test.txt" then run:

python -c "import doctest; doctest.testfile('test.txt')"

This gives me unexpected test failures:

python -c "import doctest; doctest.testfile('test.txt')"
************************************************** ********************
File "test.txt", line 5, in test.txt
Failed example:
delattr(this_module, 'f')
Exception raised:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/doctest.py", line 1212, in __run
compileflags, 1) in test.globs
File "<doctest test.txt[3]>", line 1, in <module>
delattr(this_module, 'f')
AttributeError: f
************************************************** ********************
File "test.txt", line 6, in test.txt
Failed example:
f()
Expected:
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined
Got nothing
************************************************** ********************
1 items had failures:
2 of 5 in test.txt
***Test Failed*** 2 failures.
The doctest code is executed in a module without a __name__, it seems.
Unfortunately (in this case) the builtin module serves as a fallback
helping out with its own name:
>>__name__
'__main__'
>>del __name__
__name__
'__builtin__'
What to do about it? doctest could be changed to execute code snippets in a
module with a name and a sys.modules entry though I don't see much benefit
here.

Peter
May 21 '07 #2
tag
On 21 May, 18:53, Peter Otten <__pete...@web.dewrote:
The doctest code is executed in a module without a __name__, it seems.
Unfortunately (in this case) the builtin module serves as a fallback
helping out with its own name:
>__name__
'__main__'
>del __name__
__name__

'__builtin__'

What to do about it? doctest could be changed to execute code snippets in a
module with a name and a sys.modules entry though I don't see much benefit
here.
Peter, thanks for the quick response, but I don't quite understand
what you're saying. I don't want to change doctest -- I want to find a
way to make my example pass using doctest.

doctest.testfile comes with lots of parameters, and I suspect if I
knew how to do it I could pass in the correct parameters to make this
example work. It's not what I actually want to document/test, it's a
minimal example which demonstrates the problem.

Thanks again.
>
Peter

May 21 '07 #3
tag wrote:
On 21 May, 18:53, Peter Otten <__pete...@web.dewrote:
>The doctest code is executed in a module without a __name__, it seems.
Unfortunately (in this case) the builtin module serves as a fallback
helping out with its own name:
>>__name__
'__main__'
>>del __name__
__name__

'__builtin__'

What to do about it? doctest could be changed to execute code snippets in
a module with a name and a sys.modules entry though I don't see much
benefit here.

Peter, thanks for the quick response, but I don't quite understand
what you're saying. I don't want to change doctest -- I want to find a
way to make my example pass using doctest.
The environment that doctest provides is similar to the interactive
interpreter but not identical. In particular there is no meaningful
__name__.
doctest.testfile comes with lots of parameters, and I suspect if I
knew how to do it I could pass in the correct parameters to make this
example work. It's not what I actually want to document/test, it's a
minimal example which demonstrates the problem.
Here are two alternatives:

(1)
>>def f(): pass
....
>>del f
f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined

(2)
>>def f(): pass
....
>>del globals()["f"]
f()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'f' is not defined

If these don't work you'll have to give a bit more context.

Peter
May 21 '07 #4
tag
On 21 May, 22:17, Peter Otten <__pete...@web.dewrote:
If these don't work you'll have to give a bit more context.

Peter
Thanks again Peter. Here's something much closer to what I really want
to do. You should be able to cut and paste this post into a file
"post.txt". Running the command `python -c "import doctest;
doctest.testfile('post.txt')"` gives a test failure even though
everything works fine in an interpreted Python session. I'd like to
find a way to make the doctest pass.
>>def announce(f):
.... " Return a function which announces calls to the input
function. "
.... def wrapper(*v, **k):
.... print "Calling %s" % f.__name__
.... return f(*v, **k)
.... return wrapper

We can rebind a function to announce calls to it:
>>def g(): pass
....
>>g = announce(g)
g()
Calling g

Or we can use decorator syntax:
>>@announce
.... def f(): pass
....
>>f()
Calling f

Here's a function which rebinds a function at the top level of a
module (it won't work for nested functions).
>>def announce_function(f):
.... " Rebind f within a module so that calls to f are announced. "
.... import inspect
.... setattr(inspect.getmodule(f), f.__name__, announce(f))

Let's give it a try. This next works fine in an interactive Python
session but fails when doctested.
>>def h(): pass
....
>>announce_function(h)
h()
Calling h
Here's the doctest failure:

python -c "import doctest; doctest.testfile('post.txt')"
************************************************** ********************
File "post.txt", line 37, in post.txt
Failed example:
announce_function(h)
Exception raised:
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/2.5/lib/
python2.5/doctest.py", line 1212, in __run
compileflags, 1) in test.globs
File "<doctest post.txt[8]>", line 1, in <module>
announce_function(h)
File "<doctest post.txt[6]>", line 4, in announce_function
setattr(inspect.getmodule(f), f.__name__, announce(f))
AttributeError: 'NoneType' object has no attribute 'h'
************************************************** ********************
File "post.txt", line 38, in post.txt
Failed example:
h()
Expected:
Calling h
Got nothing
************************************************** ********************
1 items had failures:
2 of 10 in post.txt
***Test Failed*** 2 failures.

May 22 '07 #5
tag wrote:
Thanks again Peter. Here's something much closer to what I really want
to do. You should be able to cut and paste this post into a file
"post.txt". Running the command `python -c "import doctest;
doctest.testfile('post.txt')"` gives a test failure even though
everything works fine in an interpreted Python session. I'd like to
find a way to make the doctest pass.
>>>def announce(f):
... " Return a function which announces calls to the input
function. "
... def wrapper(*v, **k):
... print "Calling %s" % f.__name__
... return f(*v, **k)
... return wrapper

We can rebind a function to announce calls to it:
>>>def g(): pass
...
>>>g = announce(g)
g()
Calling g

Or we can use decorator syntax:
>>>@announce
... def f(): pass
...
>>>f()
Calling f

Here's a function which rebinds a function at the top level of a
module (it won't work for nested functions).
>>>def announce_function(f):
... " Rebind f within a module so that calls to f are announced. "
... import inspect
... setattr(inspect.getmodule(f), f.__name__, announce(f))
inspect.getmodule(f) returns None because f() is not defined in a module.
You can either move f() to a helper module and then

from helper_module import f

or modify anouncement_function() to not rely on that non-existent module
>>def announce_function(f):
.... " Rebind f within a module so that calls to f are announced. "
.... f.func_globals[f.__name__] = announce(f)
....

Let's give it a try. This next works fine in an interactive Python
session but fails when doctested.
>>>def h(): pass
...
>>>announce_function(h)
h()
Calling h
Even when it works, implicitly modifying global variables is bad style.

Peter
May 22 '07 #6
tag
On 22 May, 08:59, Peter Otten <__pete...@web.dewrote:

[snip]
inspect.getmodule(f) returns None because f() is not defined in a module.
OK. But there was a module when I ran interactively?
You can either move f() to a helper module and then

from helper_module import f
Yes.
or modify anouncement_function() to not rely on that non-existent module
>def announce_function(f):

... " Rebind f within a module so that calls to f are announced. "
... f.func_globals[f.__name__] = announce(f)
...
I think this is what I should be doing. Very nice! You're modifying
f's own gloabl environment.
>
Let's give it a try. This next works fine in an interactive Python
session but fails when doctested.
>>def h(): pass
...
>>announce_function(h)
h()
Calling h

Even when it works, implicitly modifying global variables is bad style.
I have to admit it didn't feel right, but I didn't come up with the
idea you present. Thanks again for your help.

May 22 '07 #7
tag wrote:
On 22 May, 08:59, Peter Otten <__pete...@web.dewrote:
>inspect.getmodule(f) returns None because f() is not defined in a module.
OK. But there was a module when I ran interactively?
Yes. Looking into the doctest source, there is a -- deprecated -- class
called Tester that provides a module. I don't know why this approach was
dropped.

Peter
May 22 '07 #8
En Tue, 22 May 2007 04:21:06 -0300, tag <th**********@gmail.comescribió:
Here's a function which rebinds a function at the top level of a
module (it won't work for nested functions).
>>>def announce_function(f):
... " Rebind f within a module so that calls to f are announced. "
... import inspect
... setattr(inspect.getmodule(f), f.__name__, announce(f))

Let's give it a try. This next works fine in an interactive Python
session but fails when doctested.
The version given by Peter Otten may do what you want, but I'd consider if
you really need an announce_function in the first place, given all the
other ways you already have to do the same thing.
Implicitely rebinding globals does not look good.

--
Gabriel Genellina

May 22 '07 #9
tag
On 22 May, 10:11, "Gabriel Genellina" <gagsl-...@yahoo.com.arwrote:
The version given by Peter Otten may do what you want, but I'd consider if
you really need an announce_function in the first place, given all the
other ways you already have to do the same thing.
Implicitely rebinding globals does not look good.
Thanks for the advice Gabriel. The use case I have is that I'd like to
be able to decorate classes and even modules in this way:

import announce
import spam
announce.announce_module(spam)

.... code which calls into spam module

Here, "announce.announce_module" has a look in "spam", finds all the
functions and instancemethods, and decorates them (rebinds them) by
announcing calls to these functions and instancemethods.

It's something I've found useful, though clearly the behaviour of
"spam" has been drastically changed. I'd appreciate advice on better
ways to achieve this kind of thing, or why it doesn't look good.

May 22 '07 #10
tag
On 22 May, 10:11, "Gabriel Genellina" <gagsl-...@yahoo.com.arwrote:
The version given by Peter Otten may do what you want, but I'd consider if
you really need an announce_function in the first place, given all the
other ways you already have to do the same thing.
Implicitely rebinding globals does not look good.
Thanks for the advice Gabriel. The use case I have is that I'd like to
be able to decorate classes and even modules in this way:
>>import announce
import spam
announce.announce_module(spam)
Here, "announce.announce_module" has a look in "spam", finds all the
functions and instancemethods, and decorates them (rebinds them) by
announcing calls to these functions and instancemethods.

It's something I've found useful, though clearly the behaviour of
"spam" has been drastically changed. I'd appreciate advice on better
ways to achieve this kind of thing, or why it doesn't look good.

May 22 '07 #11
tag
On 22 May, 10:11, "Gabriel Genellina" <gagsl-...@yahoo.com.arwrote:
The version given by Peter Otten may do what you want, but I'd consider if
you really need an announce_function in the first place, given all the
other ways you already have to do the same thing.
Implicitely rebinding globals does not look good.
Thanks for the advice Gabriel. The use case I have is that I'd like to
be able to decorate classes and even modules in this way:

import announce
import spam
announce.announce_module(spam)

.... code which calls into spam module

Here, "announce.announce_module" has a look in "spam", finds all the
functions and instancemethods, and decorates them (rebinds them) by
announcing calls to these functions and instancemethods.

It's something I've found useful, though clearly the behaviour of
"spam" has been drastically changed. I'd appreciate advice on better
ways to achieve this kind of thing, or why it doesn't look good.

May 22 '07 #12
En Tue, 22 May 2007 08:57:29 -0300, tag <th**********@gmail.comescribió:
On 22 May, 10:11, "Gabriel Genellina" <gagsl-...@yahoo.com.arwrote:
>The version given by Peter Otten may do what you want, but I'd consider
if
you really need an announce_function in the first place, given all the
other ways you already have to do the same thing.
Implicitely rebinding globals does not look good.

Thanks for the advice Gabriel. The use case I have is that I'd like to
be able to decorate classes and even modules in this way:

import announce
import spam
announce.announce_module(spam)

... code which calls into spam module

Here, "announce.announce_module" has a look in "spam", finds all the
functions and instancemethods, and decorates them (rebinds them) by
announcing calls to these functions and instancemethods.

It's something I've found useful, though clearly the behaviour of
"spam" has been drastically changed. I'd appreciate advice on better
ways to achieve this kind of thing, or why it doesn't look good.
Ah, then you *have* a reference to the containing module. announce_module
might be something like this:

def announce_module(module):
for fname in find_all_functions_by_name_in_module(module):
function = getattr(module, fname)
setattr(module, fname, announce_function(function))

And no need to guess anything. It works even if the original function name
is not the same as the name used in the module (this may happen when you
assign a function with another name).
Remember "Explicit is better than implicit" and "In the face of ambiguity,
refuse the temptation to guess."

--
Gabriel Genellina

May 22 '07 #13

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

0
by: Paul M | last post by:
Pythoneers, IDLE doesn't use the ps2 prompt ("..." in the command line interpreter) because it supports multiline editing. This issue has been discussed before, for example see Guido's...
14
by: Pierre Rouleau | last post by:
I have a problem writing self-testable modules using doctest when these modules have internationalized strings using gettext _('...'). - The main module of an application (say app.py) calls...
2
by: Alan G Isaac | last post by:
> python doctest.py -v Running doctest.__doc__ Trying: .remove(42) Expecting: Traceback (most recent call last): File "<stdin>", line 1, in ? ValueError: list.remove(x): x not in list ok...
2
by: Michele Simionato | last post by:
Some time ago I hacked a custom solution to run doctests on text files containing documentation. The solution involved this kind of game: tester=doctest.Tester(globs={},verbose=1)...
5
by: Michele Simionato | last post by:
I am getting a strange error with this script: $ cat doctest-threads.py """ >>> import time, threading >>> def example(): .... thread.out = .... while thread.running: .... ...
1
by: David MacKay | last post by:
Hello, I'm a python-list newbie. I've got a question about doctest; perhaps a bug report. I really like doctest, but sometimes doctest gives a failure when the output looks absolutely fine to me...
3
by: notanotheridiot | last post by:
Hi, I have two strings - a docstring containing doctests and a code string containing code to be tested with those doctests. I've been trying for a day now to run the test without concatenating...
0
by: Eric Mahurin | last post by:
Noob here. Just got into python a little over a week ago... One of the (unique?) things I really like about python is the concept of doctesting. But, now I want more! Here's what I'd like to...
6
by: Bzyczek | last post by:
Hello, I have problems with running doctests if I use czech national characters in UTF-8 encoding. I have Python script, which begin with encoding definition: # -*- coding: utf-8 -*- I...
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...
1
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
1
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...
0
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
0
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated ...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.