Package Bio :: Package Application
[hide private]
[frames] | no frames]

Source Code for Package Bio.Application

  1  # Copyright 2001-2004 Brad Chapman. 
  2  # Revisions copyright 2009-2013 by Peter Cock. 
  3  # All rights reserved. 
  4  # This code is part of the Biopython distribution and governed by its 
  5  # license.  Please see the LICENSE file that should have been included 
  6  # as part of this package. 
  7  """General mechanisms to access applications in Biopython. 
  8   
  9  This module is not intended for direct use. It provides the basic objects which 
 10  are subclassed by our command line wrappers, such as: 
 11   
 12   - Bio.Align.Applications 
 13   - Bio.Blast.Applications 
 14   - Bio.Emboss.Applications 
 15   - Bio.Sequencing.Applications 
 16   
 17  These modules provide wrapper classes for command line tools to help you 
 18  construct command line strings by setting the values of each parameter. 
 19  The finished command line strings are then normally invoked via the built-in 
 20  Python module subprocess. 
 21  """ 
 22  from __future__ import print_function 
 23  from Bio._py3k import basestring 
 24   
 25  import os 
 26  import platform 
 27  import sys 
 28  import subprocess 
 29  import re 
 30   
 31  from subprocess import CalledProcessError as _ProcessCalledError 
 32   
 33  from Bio import File 
 34   
 35  #Use this regular expression to test the property names are going to 
 36  #be valid as Python properties or arguments 
 37  _re_prop_name = re.compile(r"^[a-zA-Z][a-zA-Z0-9_]*$") 
 38  assert _re_prop_name.match("t") 
 39  assert _re_prop_name.match("test") 
 40  assert _re_prop_name.match("_test") is None # we don't want private names 
 41  assert _re_prop_name.match("-test") is None 
 42  assert _re_prop_name.match("any-hyphen") is None 
 43  assert _re_prop_name.match("underscore_ok") 
 44  assert _re_prop_name.match("test_name") 
 45  assert _re_prop_name.match("test2") 
 46  #These are reserved names in Python itself, 
 47  _reserved_names = ["and", "del", "from", "not", "while", "as", "elif", 
 48                     "global", "or", "with", "assert", "else", "if", "pass", 
 49                     "yield", "break", "except", "import", "print", "class", 
 50                     "exec", "in", "raise", "continue", "finally", "is", 
 51                     "return", "def", "for", "lambda", "try"] 
 52  #These are reserved names due to the way the wrappers work 
 53  _local_reserved_names = ["set_parameter"] 
 54   
 55   
56 -class ApplicationError(_ProcessCalledError):
57 """Raised when an application returns a non-zero exit status. 58 59 The exit status will be stored in the returncode attribute, similarly 60 the command line string used in the cmd attribute, and (if captured) 61 stdout and stderr as strings. 62 63 This exception is a subclass of subprocess.CalledProcessError. 64 65 >>> err = ApplicationError(-11, "helloworld", "", "Some error text") 66 >>> err.returncode, err.cmd, err.stdout, err.stderr 67 (-11, 'helloworld', '', 'Some error text') 68 >>> print(err) 69 Command 'helloworld' returned non-zero exit status -11, 'Some error text' 70 71 """
72 - def __init__(self, returncode, cmd, stdout="", stderr=""):
73 self.returncode = returncode 74 self.cmd = cmd 75 self.stdout = stdout 76 self.stderr = stderr
77
78 - def __str__(self):
79 #get first line of any stderr message 80 try: 81 msg = self.stderr.lstrip().split("\n", 1)[0].rstrip() 82 except: 83 msg = "" 84 if msg: 85 return "Command '%s' returned non-zero exit status %d, %r" \ 86 % (self.cmd, self.returncode, msg) 87 else: 88 return "Command '%s' returned non-zero exit status %d" \ 89 % (self.cmd, self.returncode)
90
91 - def __repr__(self):
92 return "ApplicationError(%i, %s, %s, %s)" \ 93 % (self.returncode, self.cmd, self.stdout, self.stderr)
94 95
96 -class AbstractCommandline(object):
97 """Generic interface for constructing command line strings. 98 99 This class shouldn't be called directly; it should be subclassed to 100 provide an implementation for a specific application. 101 102 For a usage example we'll show one of the EMBOSS wrappers. You can set 103 options when creating the wrapper object using keyword arguments - or 104 later using their corresponding properties: 105 106 >>> from Bio.Emboss.Applications import WaterCommandline 107 >>> cline = WaterCommandline(gapopen=10, gapextend=0.5) 108 >>> cline 109 WaterCommandline(cmd='water', gapopen=10, gapextend=0.5) 110 111 You can instead manipulate the parameters via their properties, e.g. 112 113 >>> cline.gapopen 114 10 115 >>> cline.gapopen = 20 116 >>> cline 117 WaterCommandline(cmd='water', gapopen=20, gapextend=0.5) 118 119 You can clear a parameter you have already added by 'deleting' the 120 corresponding property: 121 122 >>> del cline.gapopen 123 >>> cline.gapopen 124 >>> cline 125 WaterCommandline(cmd='water', gapextend=0.5) 126 127 Once you have set the parameters you need, you can turn the object into 128 a string (e.g. to log the command): 129 130 >>> str(cline) 131 Traceback (most recent call last): 132 ... 133 ValueError: You must either set outfile (output filename), or enable filter or stdout (output to stdout). 134 135 In this case the wrapper knows certain arguments are required to construct 136 a valid command line for the tool. For a complete example, 137 138 >>> from Bio.Emboss.Applications import WaterCommandline 139 >>> water_cmd = WaterCommandline(gapopen=10, gapextend=0.5) 140 >>> water_cmd.asequence = "asis:ACCCGGGCGCGGT" 141 >>> water_cmd.bsequence = "asis:ACCCGAGCGCGGT" 142 >>> water_cmd.outfile = "temp_water.txt" 143 >>> print(water_cmd) 144 water -outfile=temp_water.txt -asequence=asis:ACCCGGGCGCGGT -bsequence=asis:ACCCGAGCGCGGT -gapopen=10 -gapextend=0.5 145 >>> water_cmd 146 WaterCommandline(cmd='water', outfile='temp_water.txt', asequence='asis:ACCCGGGCGCGGT', bsequence='asis:ACCCGAGCGCGGT', gapopen=10, gapextend=0.5) 147 148 You would typically run the command line via a standard Python operating 149 system call using the subprocess module for full control. For the simple 150 case where you just want to run the command and get the output: 151 152 stdout, stderr = water_cmd() 153 154 Note that by default we assume the underlying tool is installed on the 155 system $PATH environment variable. This is normal under Linux/Unix, but 156 may need to be done manually under Windows. Alternatively, you can specify 157 the full path to the binary as the first argument (cmd): 158 159 >>> from Bio.Emboss.Applications import WaterCommandline 160 >>> water_cmd = WaterCommandline("C:\Program Files\EMBOSS\water.exe", 161 ... gapopen=10, gapextend=0.5, 162 ... asequence="asis:ACCCGGGCGCGGT", 163 ... bsequence="asis:ACCCGAGCGCGGT", 164 ... outfile="temp_water.txt") 165 >>> print(water_cmd) 166 "C:\Program Files\EMBOSS\water.exe" -outfile=temp_water.txt -asequence=asis:ACCCGGGCGCGGT -bsequence=asis:ACCCGAGCGCGGT -gapopen=10 -gapextend=0.5 167 168 Notice that since the path name includes a space it has automatically 169 been quoted. 170 171 """ 172 #TODO - Replace the above example since EMBOSS doesn't work properly 173 #if installed into a folder with a space like "C:\Program Files\EMBOSS" 174 175 #Note the call example above is not a doctest as we can't handle EMBOSS 176 #(or any other tool) being missing in the unit tests.
177 - def __init__(self, cmd, **kwargs):
178 """Create a new instance of a command line wrapper object.""" 179 # Init method - should be subclassed! 180 # 181 # The subclass methods should look like this: 182 # 183 # def __init__(self, cmd="muscle", **kwargs): 184 # self.parameters = [...] 185 # AbstractCommandline.__init__(self, cmd, **kwargs) 186 # 187 # i.e. There should have an optional argument "cmd" to set the location 188 # of the executable (with a sensible default which should work if the 189 # command is on the path on Unix), and keyword arguments. It should 190 # then define a list of parameters, all objects derived from the base 191 # class _AbstractParameter. 192 # 193 # The keyword arguments should be any valid parameter name, and will 194 # be used to set the associated parameter. 195 self.program_name = cmd 196 try: 197 parameters = self.parameters 198 except AttributeError: 199 raise AttributeError("Subclass should have defined self.parameters") 200 #Create properties for each parameter at run time 201 aliases = set() 202 for p in parameters: 203 if not p.names: 204 assert isinstance(p, _StaticArgument), p 205 continue 206 for name in p.names: 207 if name in aliases: 208 raise ValueError("Parameter alias %s multiply defined" 209 % name) 210 aliases.add(name) 211 name = p.names[-1] 212 if _re_prop_name.match(name) is None: 213 raise ValueError("Final parameter name %s cannot be used as " 214 "an argument or property name in python" 215 % repr(name)) 216 if name in _reserved_names: 217 raise ValueError("Final parameter name %s cannot be used as " 218 "an argument or property name because it is " 219 "a reserved word in python" % repr(name)) 220 if name in _local_reserved_names: 221 raise ValueError("Final parameter name %s cannot be used as " 222 "an argument or property name due to the " 223 "way the AbstractCommandline class works" 224 % repr(name)) 225 226 #Beware of binding-versus-assignment confusion issues 227 def getter(name): 228 return lambda x: x._get_parameter(name)
229 230 def setter(name): 231 return lambda x, value: x.set_parameter(name, value)
232 233 def deleter(name): 234 return lambda x: x._clear_parameter(name) 235 236 doc = p.description 237 if isinstance(p, _Switch): 238 doc += "\n\nThis property controls the addition of the %s " \ 239 "switch, treat this property as a boolean." % p.names[0] 240 else: 241 doc += "\n\nThis controls the addition of the %s parameter " \ 242 "and its associated value. Set this property to the " \ 243 "argument value required." % p.names[0] 244 prop = property(getter(name), setter(name), deleter(name), doc) 245 setattr(self.__class__, name, prop) # magic! 246 for key, value in kwargs.items(): 247 self.set_parameter(key, value) 248
249 - def _validate(self):
250 """Make sure the required parameters have been set (PRIVATE). 251 252 No return value - it either works or raises a ValueError. 253 254 This is a separate method (called from __str__) so that subclasses may 255 override it. 256 """ 257 for p in self.parameters: 258 #Check for missing required parameters: 259 if p.is_required and not(p.is_set): 260 raise ValueError("Parameter %s is not set." 261 % p.names[-1])
262 #Also repeat the parameter validation here, just in case? 263
264 - def __str__(self):
265 """Make the commandline string with the currently set options. 266 267 e.g. 268 >>> from Bio.Emboss.Applications import WaterCommandline 269 >>> cline = WaterCommandline(gapopen=10, gapextend=0.5) 270 >>> cline.asequence = "asis:ACCCGGGCGCGGT" 271 >>> cline.bsequence = "asis:ACCCGAGCGCGGT" 272 >>> cline.outfile = "temp_water.txt" 273 >>> print(cline) 274 water -outfile=temp_water.txt -asequence=asis:ACCCGGGCGCGGT -bsequence=asis:ACCCGAGCGCGGT -gapopen=10 -gapextend=0.5 275 >>> str(cline) 276 'water -outfile=temp_water.txt -asequence=asis:ACCCGGGCGCGGT -bsequence=asis:ACCCGAGCGCGGT -gapopen=10 -gapextend=0.5' 277 """ 278 self._validate() 279 commandline = "%s " % _escape_filename(self.program_name) 280 for parameter in self.parameters: 281 if parameter.is_set: 282 #This will include a trailing space: 283 commandline += str(parameter) 284 return commandline.strip() # remove trailing space
285
286 - def __repr__(self):
287 """Return a representation of the command line object for debugging. 288 289 e.g. 290 >>> from Bio.Emboss.Applications import WaterCommandline 291 >>> cline = WaterCommandline(gapopen=10, gapextend=0.5) 292 >>> cline.asequence = "asis:ACCCGGGCGCGGT" 293 >>> cline.bsequence = "asis:ACCCGAGCGCGGT" 294 >>> cline.outfile = "temp_water.txt" 295 >>> print(cline) 296 water -outfile=temp_water.txt -asequence=asis:ACCCGGGCGCGGT -bsequence=asis:ACCCGAGCGCGGT -gapopen=10 -gapextend=0.5 297 >>> cline 298 WaterCommandline(cmd='water', outfile='temp_water.txt', asequence='asis:ACCCGGGCGCGGT', bsequence='asis:ACCCGAGCGCGGT', gapopen=10, gapextend=0.5) 299 """ 300 answer = "%s(cmd=%s" % (self.__class__.__name__, repr(self.program_name)) 301 for parameter in self.parameters: 302 if parameter.is_set: 303 if isinstance(parameter, _Switch): 304 answer += ", %s=True" % parameter.names[-1] 305 else: 306 answer += ", %s=%s" \ 307 % (parameter.names[-1], repr(parameter.value)) 308 answer += ")" 309 return answer
310
311 - def _get_parameter(self, name):
312 """Get a commandline option value.""" 313 for parameter in self.parameters: 314 if name in parameter.names: 315 if isinstance(parameter, _Switch): 316 return parameter.is_set 317 else: 318 return parameter.value 319 raise ValueError("Option name %s was not found." % name)
320
321 - def _clear_parameter(self, name):
322 """Reset or clear a commandline option value.""" 323 cleared_option = False 324 for parameter in self.parameters: 325 if name in parameter.names: 326 parameter.value = None 327 parameter.is_set = False 328 cleared_option = True 329 if not cleared_option: 330 raise ValueError("Option name %s was not found." % name)
331
332 - def set_parameter(self, name, value = None):
333 """Set a commandline option for a program (OBSOLETE). 334 335 Every parameter is available via a property and as a named 336 keyword when creating the instance. Using either of these is 337 preferred to this legacy set_parameter method which is now 338 OBSOLETE, and likely to be DEPRECATED and later REMOVED in 339 future releases. 340 """ 341 set_option = False 342 for parameter in self.parameters: 343 if name in parameter.names: 344 if isinstance(parameter, _Switch): 345 if value is None: 346 import warnings 347 warnings.warn("For a switch type argument like %s, " 348 "we expect a boolean. None is treated " 349 "as FALSE!" % parameter.names[-1]) 350 parameter.is_set = bool(value) 351 set_option = True 352 else: 353 if value is not None: 354 self._check_value(value, name, parameter.checker_function) 355 parameter.value = value 356 parameter.is_set = True 357 set_option = True 358 if not set_option: 359 raise ValueError("Option name %s was not found." % name)
360
361 - def _check_value(self, value, name, check_function):
362 """Check whether the given value is valid. 363 364 No return value - it either works or raises a ValueError. 365 366 This uses the passed function 'check_function', which can either 367 return a [0, 1] (bad, good) value or raise an error. Either way 368 this function will raise an error if the value is not valid, or 369 finish silently otherwise. 370 """ 371 if check_function is not None: 372 is_good = check_function(value) # May raise an exception 373 assert is_good in [0, 1, True, False] 374 if not is_good: 375 raise ValueError("Invalid parameter value %r for parameter %s" 376 % (value, name))
377
378 - def __setattr__(self, name, value):
379 """Set attribute name to value (PRIVATE). 380 381 This code implements a workaround for a user interface issue. 382 Without this __setattr__ attribute-based assignment of parameters 383 will silently accept invalid parameters, leading to known instances 384 of the user assuming that parameters for the application are set, 385 when they are not. 386 387 >>> from Bio.Emboss.Applications import WaterCommandline 388 >>> cline = WaterCommandline(gapopen=10, gapextend=0.5, stdout=True) 389 >>> cline.asequence = "a.fasta" 390 >>> cline.bsequence = "b.fasta" 391 >>> cline.csequence = "c.fasta" 392 Traceback (most recent call last): 393 ... 394 ValueError: Option name csequence was not found. 395 >>> print(cline) 396 water -stdout -asequence=a.fasta -bsequence=b.fasta -gapopen=10 -gapextend=0.5 397 398 This workaround uses a whitelist of object attributes, and sets the 399 object attribute list as normal, for these. Other attributes are 400 assumed to be parameters, and passed to the self.set_parameter method 401 for validation and assignment. 402 """ 403 if name in ['parameters', 'program_name']: # Allowed attributes 404 self.__dict__[name] = value 405 else: 406 self.set_parameter(name, value) # treat as a parameter
407
408 - def __call__(self, stdin=None, stdout=True, stderr=True, 409 cwd=None, env=None):
410 """Executes the command, waits for it to finish, and returns output. 411 412 Runs the command line tool and waits for it to finish. If it returns 413 a non-zero error level, an exception is raised. Otherwise two strings 414 are returned containing stdout and stderr. 415 416 The optional stdin argument should be a string of data which will be 417 passed to the tool as standard input. 418 419 The optional stdout and stderr argument may be filenames (string), 420 but otherwise are treated as a booleans, and control if the output 421 should be captured as strings (True, default), or ignored by sending 422 it to /dev/null to avoid wasting memory (False). If sent to a file 423 or ignored, then empty string(s) are returned. 424 425 The optional cwd argument is a string giving the working directory 426 to run the command from. See Python's subprocess module documentation 427 for more details. 428 429 The optional env argument is a dictionary setting the environment 430 variables to be used in the new process. By default the current 431 process' environment variables are used. See Python's subprocess 432 module documentation for more details. 433 434 Default example usage: 435 436 from Bio.Emboss.Applications import WaterCommandline 437 water_cmd = WaterCommandline(gapopen=10, gapextend=0.5, 438 stdout=True, auto=True, 439 asequence="a.fasta", bsequence="b.fasta") 440 print "About to run:\n%s" % water_cmd 441 std_output, err_output = water_cmd() 442 443 This functionality is similar to subprocess.check_output() added in 444 Python 2.7. In general if you require more control over running the 445 command, use subprocess directly. 446 447 As of Biopython 1.56, when the program called returns a non-zero error 448 level, a custom ApplicationError exception is raised. This includes 449 any stdout and stderr strings captured as attributes of the exception 450 object, since they may be useful for diagnosing what went wrong. 451 """ 452 if not stdout: 453 stdout_arg = open(os.devnull, "w") 454 elif isinstance(stdout, basestring): 455 stdout_arg = open(stdout, "w") 456 else: 457 stdout_arg = subprocess.PIPE 458 459 if not stderr: 460 stderr_arg = open(os.devnull, "w") 461 elif isinstance(stderr, basestring): 462 if stdout == stderr: 463 stderr_arg = stdout_arg #Write both to the same file 464 else: 465 stderr_arg = open(stderr, "w") 466 else: 467 stderr_arg = subprocess.PIPE 468 469 #We may not need to supply any piped input, but we setup the 470 #standard input pipe anyway as a work around for a python 471 #bug if this is called from a Windows GUI program. For 472 #details, see http://bugs.python.org/issue1124861 473 # 474 #Using universal newlines is important on Python 3, this 475 #gives unicode handles rather than bytes handles. 476 477 #Windows 7 and 8 want shell = True 478 #platform is easier to understand that sys to determine 479 #windows version 480 if sys.platform != "win32": 481 use_shell = True 482 else: 483 win_ver = platform.win32_ver()[0] 484 if win_ver in ["7", "8"]: 485 use_shell = True 486 else: 487 use_shell = False 488 child_process = subprocess.Popen(str(self), stdin=subprocess.PIPE, 489 stdout=stdout_arg, stderr=stderr_arg, 490 universal_newlines=True, 491 cwd=cwd, env=env, 492 shell=use_shell) 493 #Use .communicate as can get deadlocks with .wait(), see Bug 2804 494 stdout_str, stderr_str = child_process.communicate(stdin) 495 if not stdout: 496 assert not stdout_str, stdout_str 497 if not stderr: 498 assert not stderr_str, stderr_str 499 return_code = child_process.returncode 500 501 #Particularly important to close handles on Jython and PyPy 502 #(where garbage collection is less predictable) and on Windows 503 #(where cannot delete files with an open handle): 504 if stdout and isinstance(stdout, basestring): 505 stdout_arg.close() 506 if stderr and isinstance(stderr, basestring) and stdout != stderr: 507 stderr_arg.close() 508 509 if return_code: 510 raise ApplicationError(return_code, str(self), 511 stdout_str, stderr_str) 512 return stdout_str, stderr_str
513 514
515 -class _AbstractParameter:
516 """A class to hold information about a parameter for a commandline. 517 518 Do not use this directly, instead use one of the subclasses. 519 """
520 - def __init__(self):
521 raise NotImplementedError
522
523 - def __str__(self):
524 raise NotImplementedError
525 526
527 -class _Option(_AbstractParameter):
528 """Represent an option that can be set for a program. 529 530 This holds UNIXish options like --append=yes and -a yes, 531 where a value (here "yes") is generally expected. 532 533 For UNIXish options like -kimura in clustalw which don't 534 take a value, use the _Switch object instead. 535 536 Attributes: 537 538 o names -- a list of string names (typically two entries) by which 539 the parameter can be set via the legacy set_parameter method 540 (eg ["-a", "--append", "append"]). The first name in list is used 541 when building the command line. The last name in the list is a 542 "human readable" name describing the option in one word. This 543 must be a valid Python identifer as it is used as the property 544 name and as a keyword argument, and should therefore follow PEP8 545 naming. 546 547 o description -- a description of the option. This is used as 548 the property docstring. 549 550 o filename -- True if this argument is a filename and should be 551 automatically quoted if it contains spaces. 552 553 o checker_function -- a reference to a function that will determine 554 if a given value is valid for this parameter. This function can either 555 raise an error when given a bad value, or return a [0, 1] decision on 556 whether the value is correct. 557 558 o equate -- should an equals sign be inserted if a value is used? 559 560 o is_required -- a flag to indicate if the parameter must be set for 561 the program to be run. 562 563 o is_set -- if the parameter has been set 564 565 o value -- the value of a parameter 566 """
567 - def __init__(self, names, description, filename=False, checker_function=None, 568 is_required=False, equate=True):
569 self.names = names 570 assert isinstance(description, basestring), \ 571 "%r for %s" % (description, names[-1]) 572 self.is_filename = filename 573 self.checker_function = checker_function 574 self.description = description 575 self.equate = equate 576 self.is_required = is_required 577 578 self.is_set = False 579 self.value = None
580
581 - def __str__(self):
582 """Return the value of this option for the commandline. 583 584 Includes a trailing space. 585 """ 586 # Note: Before equate was handled explicitly, the old 587 # code would do either "--name " or "--name=value ", 588 # or " -name " or " -name value ". This choice is now 589 # now made explicitly when setting up the option. 590 if self.value is None: 591 return "%s " % self.names[0] 592 if self.is_filename: 593 v = _escape_filename(self.value) 594 else: 595 v = str(self.value) 596 if self.equate: 597 return "%s=%s " % (self.names[0], v) 598 else: 599 return "%s %s " % (self.names[0], v)
600 601
602 -class _Switch(_AbstractParameter):
603 """Represent an optional argument switch for a program. 604 605 This holds UNIXish options like -kimura in clustalw which don't 606 take a value, they are either included in the command string 607 or omitted. 608 609 o names -- a list of string names (typically two entries) by which 610 the parameter can be set via the legacy set_parameter method 611 (eg ["-a", "--append", "append"]). The first name in list is used 612 when building the command line. The last name in the list is a 613 "human readable" name describing the option in one word. This 614 must be a valid Python identifer as it is used as the property 615 name and as a keyword argument, and should therefore follow PEP8 616 naming. 617 618 o description -- a description of the option. This is used as 619 the property docstring. 620 621 o is_set -- if the parameter has been set 622 623 NOTE - There is no value attribute, see is_set instead, 624 """
625 - def __init__(self, names, description):
626 self.names = names 627 self.description = description 628 self.is_set = False 629 self.is_required = False
630
631 - def __str__(self):
632 """Return the value of this option for the commandline. 633 634 Includes a trailing space. 635 """ 636 assert not hasattr(self, "value") 637 if self.is_set: 638 return "%s " % self.names[0] 639 else: 640 return ""
641 642
643 -class _Argument(_AbstractParameter):
644 """Represent an argument on a commandline. 645 646 The names argument should be a list containing one string. 647 This must be a valid Python identifer as it is used as the 648 property name and as a keyword argument, and should therefore 649 follow PEP8 naming. 650 """
651 - def __init__(self, names, description, filename=False, 652 checker_function=None, is_required=False):
653 #if len(names) != 1: 654 # raise ValueError("The names argument to _Argument should be a " 655 # "single entry list with a PEP8 property name.") 656 self.names = names 657 assert isinstance(description, basestring), \ 658 "%r for %s" % (description, names[-1]) 659 self.is_filename = filename 660 self.checker_function = checker_function 661 self.description = description 662 self.is_required = is_required 663 self.is_set = False 664 self.value = None
665
666 - def __str__(self):
667 if self.value is None: 668 return " " 669 elif self.is_filename: 670 return "%s " % _escape_filename(self.value) 671 else: 672 return "%s " % self.value
673 674
675 -class _StaticArgument(_AbstractParameter):
676 """Represent a static (read only) argument on a commandline. 677 678 This is not intended to be exposed as a named argument or 679 property of a command line wrapper object. 680 """
681 - def __init__(self, value):
682 self.names = [] 683 self.is_required = False 684 self.is_set = True 685 self.value = value
686
687 - def __str__(self):
688 return "%s " % self.value
689 690
691 -def _escape_filename(filename):
692 """Escape filenames with spaces by adding quotes (PRIVATE). 693 694 Note this will not add quotes if they are already included: 695 696 >>> print((_escape_filename('example with spaces'))) 697 "example with spaces" 698 >>> print((_escape_filename('"example with spaces"'))) 699 "example with spaces" 700 """ 701 #Is adding the following helpful 702 #if os.path.isfile(filename): 703 # #On Windows, if the file exists, we can ask for 704 # #its alternative short name (DOS style 8.3 format) 705 # #which has no spaces in it. Note that this name 706 # #is not portable between machines, or even folder! 707 # try: 708 # import win32api 709 # short = win32api.GetShortPathName(filename) 710 # assert os.path.isfile(short) 711 # return short 712 # except ImportError: 713 # pass 714 if " " not in filename: 715 return filename 716 #We'll just quote it - works on Windows, Mac OS X etc 717 if filename.startswith('"') and filename.endswith('"'): 718 #Its already quoted 719 return filename 720 else: 721 return '"%s"' % filename
722 723
724 -def _test():
725 """Run the Bio.Application module's doctests.""" 726 import doctest 727 doctest.testmod(verbose=1)
728 729 if __name__ == "__main__": 730 #Run the doctests 731 _test() 732