1 """General mechanisms to access applications in biopython.
8 def generic_run(commandline):
9 """Run an application with the given commandline.
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.
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.
20 # print str(commandline)
22 #Try and use subprocess (available in python 2.4+)
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"))
44 error_code = child.wait()
47 #For python 2.3 can't use subprocess, using popen2 instead
48 #(deprecated in python 2.6)
50 if sys.platform[:3]=='win':
51 # Windows does not have popen2.Popen3
52 r, w, e = popen2.popen3(str(commandline))
60 # No way to get the error code; setting it to a dummy variable
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
68 # here are the file descriptors
80 error_code = os.WEXITSTATUS(child.wait())
82 return ApplicationResult(commandline, error_code), \
83 File.UndoHandle(StringIO.StringIO(r_out)), \
84 File.UndoHandle(StringIO.StringIO(e_out))
86 class ApplicationResult:
87 """Make results of a program available through a standard interface.
89 This tries to pick up output information available from the program
90 and make it available programmatically.
92 def __init__(self, application_cl, return_code):
93 """Intialize with the commandline from the program.
95 self._cl = application_cl
97 # provide the return code of the application
98 self.return_code = return_code
100 # get the application dependent results we can provide
101 # right now the only results we handle are output files
104 for parameter in self._cl.parameters:
105 if "file" in parameter.param_types and \
106 "output" in parameter.param_types:
108 self._results[parameter.names[-1]] = parameter.value
110 def get_result(self, output_name):
111 """Retrieve result information for the given output.
113 return self._results[output_name]
115 def available_results(self):
116 """Retrieve a list of all available results.
118 result_names = self._results.keys()
122 class AbstractCommandline:
123 """Generic interface for running applications from biopython.
125 This class shouldn't be called directly; it should be subclassed to
126 provide an implementation for a specific application.
129 self.program_name = ""
133 """Make the commandline with the currently set options.
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)
140 commandline += str(parameter)
144 def set_parameter(self, name, value = None):
145 """Set a commandline option for a program.
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
157 raise ValueError("Option name %s was not found." % name)
159 def _check_value(self, value, name, check_function):
160 """Check whether the given value is valid.
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.
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
172 "Invalid parameter value %r for parameter %s" %
175 class _AbstractParameter:
176 """A class to hold information about a parameter for a commandline.
178 Do not use this directly, instead use one of the subclasses.
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
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'
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.
198 o description -- a description of the option.
200 o is_required -- a flag to indicate if the parameter must be set for
201 the program to be run.
203 o is_set -- if the parameter has been set
205 o value -- the value of a parameter
207 def __init__(self, names = [], types = [], checker_function = None,
208 is_required = 0, description = ""):
210 self.param_types = types
211 self.checker_function = checker_function
212 self.description = description
213 self.is_required = is_required
218 class _Option(_AbstractParameter):
219 """Represent an option that can be set for a program.
221 This holds UNIXish options like --append=yes and -a yes
224 """Return the value of this option for the commandline.
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
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
239 raise ValueError("Unrecognized option type: %s" % self.names[0])
243 class _Argument(_AbstractParameter):
244 """Represent an argument on a commandline.
247 if self.value is not None:
248 return "%s " % self.value