Mac binaries
[jabaws.git] / website / archive / binaries / mac / src / disembl / biopython-1.50 / Bio / Application / __init__.py
1 """General mechanisms to access applications in biopython.
2 """
3 import os, sys
4 import StringIO
5
6 from Bio import File
7
8 def generic_run(commandline):
9     """Run an application with the given commandline.
10
11     This expects a pre-built commandline that derives from 
12     AbstractCommandline, and returns a ApplicationResult object
13     to get results from a program, along with handles of the
14     standard output and standard error.
15
16     WARNING - This will read in the full program output into memory!
17     This may be in issue when the program write a large amount of
18     data to standard output.
19     """
20     # print str(commandline)
21
22     #Try and use subprocess (available in python 2.4+)
23     try :
24         import subprocess, sys
25         #We don't need to supply any piped input, but we setup the
26         #standard input pipe anyway as a work around for a python
27         #bug if this is called from a Windows GUI program.  For
28         #details, see http://bugs.python.org/issue1124861
29         child = subprocess.Popen(str(commandline),
30                                  stdin=subprocess.PIPE,
31                                  stdout=subprocess.PIPE,
32                                  stderr=subprocess.PIPE,
33                                  shell=(sys.platform!="win32"))
34         child.stdin.close()
35         r = child.stdout
36         e = child.stderr 
37
38         r_out = r.read()
39         e_out = e.read()
40         r.close()
41         e.close()
42
43         # capture error code
44         error_code = child.wait()
45
46     except ImportError :
47         #For python 2.3 can't use subprocess, using popen2 instead
48         #(deprecated in python 2.6)
49         import popen2
50         if sys.platform[:3]=='win':
51             # Windows does not have popen2.Popen3
52             r, w, e = popen2.popen3(str(commandline))
53         
54             r_out = r.read()
55             e_out = e.read()
56             w.close()
57             r.close()
58             e.close()
59
60             # No way to get the error code; setting it to a dummy variable
61             error_code = 0
62
63         else:
64             child = popen2.Popen3(str(commandline), 1)
65             # get information and close the files, so if we call this function
66             # repeatedly we won't end up with too many open files
67
68             # here are the file descriptors
69             r = child.fromchild
70             w = child.tochild
71             e = child.childerr
72         
73             r_out = r.read()
74             e_out = e.read()
75             w.close()
76             r.close()
77             e.close()
78         
79             # capture error code
80             error_code = os.WEXITSTATUS(child.wait())
81
82     return ApplicationResult(commandline, error_code), \
83            File.UndoHandle(StringIO.StringIO(r_out)), \
84            File.UndoHandle(StringIO.StringIO(e_out))
85
86 class ApplicationResult:
87     """Make results of a program available through a standard interface.
88     
89     This tries to pick up output information available from the program
90     and make it available programmatically.
91     """
92     def __init__(self, application_cl, return_code):
93         """Intialize with the commandline from the program.
94         """
95         self._cl = application_cl
96
97         # provide the return code of the application
98         self.return_code = return_code
99
100         # get the application dependent results we can provide
101         # right now the only results we handle are output files
102         self._results = {}
103
104         for parameter in self._cl.parameters:
105             if "file" in parameter.param_types and \
106                "output" in parameter.param_types:
107                 if parameter.is_set:
108                     self._results[parameter.names[-1]] = parameter.value
109
110     def get_result(self, output_name):
111         """Retrieve result information for the given output.
112         """
113         return self._results[output_name]
114
115     def available_results(self):
116         """Retrieve a list of all available results.
117         """
118         result_names = self._results.keys()
119         result_names.sort()
120         return result_names
121
122 class AbstractCommandline:
123     """Generic interface for running applications from biopython.
124
125     This class shouldn't be called directly; it should be subclassed to
126     provide an implementation for a specific application.
127     """
128     def __init__(self):
129         self.program_name = ""
130         self.parameters = []
131     
132     def __str__(self):
133         """Make the commandline with the currently set options.
134         """
135         commandline = "%s " % self.program_name
136         for parameter in self.parameters:
137             if parameter.is_required and not(parameter.is_set):
138                 raise ValueError("Parameter %s is not set." % parameter.names)
139             if parameter.is_set:
140                 commandline += str(parameter)
141
142         return commandline
143
144     def set_parameter(self, name, value = None):
145         """Set a commandline option for a program.
146         """
147         set_option = 0
148         for parameter in self.parameters:
149             if name in parameter.names:
150                 if value is not None:
151                     self._check_value(value, name, parameter.checker_function)
152                     parameter.value = value
153                 parameter.is_set = 1
154                 set_option = 1
155
156         if set_option == 0:
157             raise ValueError("Option name %s was not found." % name)
158
159     def _check_value(self, value, name, check_function):
160         """Check whether the given value is valid.
161
162         This uses the passed function 'check_function', which can either
163         return a [0, 1] (bad, good) value or raise an error. Either way
164         this function will raise an error if the value is not valid, or
165         finish silently otherwise.
166         """
167         if check_function is not None:
168             is_good = check_function(value)
169             if is_good in [0, 1]: # if we are dealing with a good/bad check
170                 if not(is_good):
171                     raise ValueError(
172                             "Invalid parameter value %r for parameter %s" %
173                             (value, name))
174                     
175 class _AbstractParameter:
176     """A class to hold information about a parameter for a commandline.
177
178     Do not use this directly, instead use one of the subclasses.
179
180     Attributes:
181
182     o names -- a list of string names by which the parameter can be
183     referenced (ie. ["-a", "--append", "append"]). The first name in
184     the list is considered to be the one that goes on the commandline,
185     for those parameters that print the option. The last name in the list
186     is assumed to be a "human readable" name describing the option in one
187     word.
188
189     o param_type -- a list of string describing the type of parameter, 
190     which can help let programs know how to use it. Example descriptions
191     include 'input', 'output', 'file'
192
193     o checker_function -- a reference to a function that will determine
194     if a given value is valid for this parameter. This function can either
195     raise an error when given a bad value, or return a [0, 1] decision on
196     whether the value is correct.
197
198     o description -- a description of the option.
199
200     o is_required -- a flag to indicate if the parameter must be set for
201     the program to be run.
202
203     o is_set -- if the parameter has been set
204
205     o value -- the value of a parameter
206     """
207     def __init__(self, names = [], types = [], checker_function = None, 
208                  is_required = 0, description = ""):
209         self.names = names
210         self.param_types = types
211         self.checker_function = checker_function
212         self.description = description
213         self.is_required = is_required
214
215         self.is_set = 0
216         self.value = None
217
218 class _Option(_AbstractParameter):
219     """Represent an option that can be set for a program.
220
221     This holds UNIXish options like --append=yes and -a yes
222     """
223     def __str__(self):
224         """Return the value of this option for the commandline.
225         """
226         # first deal with long options
227         if self.names[0].find("--") >= 0:
228             output = "%s" % self.names[0]
229             if self.value is not None:
230                 output += "=%s " % self.value
231             else:
232                 output += " "
233         # now short options
234         elif self.names[0].find("-") >= 0:
235             output = "%s " % self.names[0]
236             if self.value is not None:
237                 output += "%s " % self.value
238         else:
239             raise ValueError("Unrecognized option type: %s" % self.names[0])
240
241         return output
242
243 class _Argument(_AbstractParameter):
244     """Represent an argument on a commandline.
245     """
246     def __str__(self):
247         if self.value is not None:
248             return "%s " % self.value
249         else:
250             return " "