how to access source tree in Twisted trial tests? - python

In my trial test case, I want to run scripts from my source tree. Trial changes the working directory, so simple relative paths don't work. In practice, Trial's temporary directory is inside the source tree, but assuming that to be the case seems suboptimal. I.e., I could do:
def source_file(p):
return os.path.join('..', p)
Is there a better way?

If you want to find a file next to your test and run it as a script, you can just do this:
from twisted.python.modules import getModule
script = getModule(__name__).filePath.path
# ...
reactor.spawnProcess(..., script, ...)
You can also use this to support storing your code in a zip file, although invoking it with Python becomes a little more difficult that way. Have you considered just using python -m?

Related

Making a directory for a file

I was making a exercise generator algorithm for my friend, but I stumbled across a problem. It is a python program, and I wanted to generate a folder in a directory that was above the program's location (like, the python file is in 'C:\Documents\foo' and the folder should be created in 'C:\Documents') so that it could then store the file the program created. Is there a way to do this or should I try something else?
Use the path argument of the os.mkdir() function.
Getting the current script directory is not a built-in feature, but there are multiple hacks suggested here.
Once you get the current script directory, you can build a path based off of that.
Not super familiar with Python in a Windows environment, but this should be easily do-able. Here is a similar question that might be worth looking at: How to check if a directory exists and create it if necessary?
Looks like the pathlib module might do what you are looking for.
from pathlib import Path
path = Path("/my/directory/filename.txt")
try:
if not path.parent.exists():
path.parent.mkdir(parents=True)
except OSError:
# handle error; you can also catch specific errors like
# FileExistsError and so on.
Appears to work on Win 7 with Python 2.7.8 as described:
import os.path
createDir = '\\'.join((os.path.abspath(os.path.join(os.getcwd(), os.pardir)), 'Foo'))
if not os.path.exists(createDir):
os.makedirs(createDir)

python unittest xml files created in different folder when test fails

The following code results in the log file printed to different folders depending on whether the test passes or not. I have a test case with one test purpose. During the running of the test, it does a chdir().
If the test result is fail (an assert* fails), the xml file is written to the test's current directory. If the test result is pass, then the xml file is written to the start folder. See the code snippet for how I specify the log file folder. Other than using full paths, is there a way to make python unittest always write it to the start folder?
logFolderName = "TestMyStuff_detail-" +str(scriptPid)
unittest.main(testRunner=xmlrunner.XMLTestRunner(output=logFolderName),
failfast=False)
Other than using full paths, is there a way to make python unittest always write it to the start folder?
Doubtful since relative paths will always be relative to the current working directory. If your test changes the current working directory, you're kind of out of luck.
With that said, it shouldn't be too hard to use a full path:
import os
cwd = os.getcwd()
localLogFolderName = "TestMyStuff_detail-" +str(scriptPid)
logFolderName = os.path.abspath(os.path.join(cwd, localLogFolderName))
you could use a fixed path to write your output.
Something like
path_to_my_output_folder="/path/to/output/"
test1_write_xml(path_to_my_output_folder+"file1.xml")
test2_write_xml(path_to_my_output_folder+"file2.xml")
test3_write_xml(path_to_my_output_folder+"file3.xml")

Python function that navigates to top level module directory

I'm trying to write a function in python that navigates to the top level directory of the project i'm working on for bookkeeping purposes. Instead of writing abs paths everywhere which may change depending on the machine, I think this would be easier.
However, my funct isn't super sophisticated and goes into inf loops in situations. Does anyone have a good strategy for something like this?
def chdir_top():
while os.getcwd().split('/')[-1] != "myproj":
os.chdir('..')
if os.getcwd().split('/')[-2] != "myproj" and
"myproj" in os.listdir(os.getcwd()):
os.chdir("myproj")
Thank you.
Do not use os.getcwd() for this; use the module-level __file__ name instead. If the current working directory is elsewhere, you end up in an infinite loop when you reach the root directory and continually fail to go up one directory.
import os.path
here = os.path.dirname(os.path.abspath(__file__))
Now here is a path to the directory containing the current Python file. Use that to find the top of your project (not by using chdir() but by using os.path functions).

Open a file from PYTHONPATH

In a program, and obviously being influenced by the way Java does things, I want to read a static file (a log configuration file, actually) from a directory within the interpreter's PYTHONPATH. I know I could do something like:
import foo
a = foo.__path__
conf = open(a[0] + "/logging.conf")
but I don't know if this is the "Pythonic" way of doing things. How could I distribute the logging configuration file in a way that my application does not need to be externally configured to read it?
In general, that's fine, though I'm not sure you want a[0] above (that will just give you the first character of the path), and you should use os.path.join instead of just appending / to be cross-platform compatible. You might consider making the path canonical, i.e. os.path.abspath(os.path.dirname(foo.__path__)). Note that it won't work if __path__ is in a zip file or other import trickery is in use, but I wouldn't worry about that (it's not normal to do so for the main program in Python, unlike Java).
If you do want to support zipped files, there's pkg_resources, but that's somewhat deprecated at this point (there's no corresponding API I could see in the new packaging module).
Here's a snippet based on the link Nix posted upthread but written in a more functional style:
def search_path(pathname_suffix):
cands = [os.path.join(d,pathname_suffix) for d in sys.path]
try:
return filter(os.path.exists, cands)[0]
except IndexError:
return None

I want to load all of the unit-tests in a tree, can it be done?

I have a heirarchical folder full of Python unit-tests. They are all importable ".py" files which define TestCase objects. This folder contains thousands of files in many nested subdirectories and was written by somebody else. I do not have permission to change it, I just have to run it.
I want to generate a single TestSuite object which contains all of the TestCases in the folder. Is there an easy and elegant way to do this?
Thanks
The nose application may be useful for you, either directly, or to show how to implement this.
http://code.google.com/p/python-nose/ seems to be the home page.
Basically, what you want to do is walk the source tree (os.walk), use imp.load_module
to load the module, use unittest.defaultTestLoader to load the tests from the module into a TestSuite, and then use that in whatever way you need to use it.
Or at least that's approximately what I do in my custom TestRunner implementation
(bzr get http://code.liw.fi/coverage-test-runner/bzr/trunk).
Look at the unittest.TestLoader (https://docs.python.org/library/unittest.html#loading-and-running-tests)
And the os.walk (https://docs.python.org/library/os.html#files-and-directories)
You should be able to traverse your package tree using the TestLoader to build a suite which you can then run.
Something along the lines of this.
runner = unittest.TextTestRunner()
superSuite = unittest.TestSuite()
for path, dirs, files in os.walk( 'path/to/tree' ):
# if a CVS dir or whatever: continue
for f in files:
# if not a python file: continue
suite= unittest.defaultTestLoader.loadTestsFromModule( os.path.join(path,f)
superSuite .addTests(suite ) # OR runner.run( suite)
runner.run( superSuite )
You can either walk through the tree simply running each test (runner.run(suite)) or you can accumulate a superSuite of all individual suites and run the whole mass as a single test (runner.run( superSuite )).
You don't need to do both, but I included both sets of suggestions in the above (untested) code.
The test directory of the Python Library source shows the way.
The README file describes how to write Python Regression Tests for library modules.
The regrtest.py module starts with:
"""Regression test.
This will find all modules whose name is "test_*" in the test
directory, and run them.

Categories

Resources