Package PyFoam :: Package ThirdParty :: Package Gnuplot :: Module termdefs
[hide private]
[frames] | no frames]

Source Code for Module PyFoam.ThirdParty.Gnuplot.termdefs

  1  # $Id: termdefs.py 302 2008-01-14 22:15:19Z bmcage $ 
  2   
  3  # Copyright (C) 2001-2003 Michael Haggerty <mhagger@alum.mit.edu> 
  4  # 
  5  # This file is licensed under the GNU Lesser General Public License 
  6  # (LGPL).  See LICENSE.txt for details. 
  7   
  8  """Terminal definition file. 
  9   
 10  This module describes the options available to gnuplot's various 
 11  terminals.  For the moment, it only supports a few terminals, but the 
 12  infrastructure is here to add others as they are needed. 
 13   
 14  Part of the trick is that the 'set terminal' command takes myriad 
 15  suboptions with various argument types, and order is sometimes 
 16  significant.  The other part of the trick is that there are over 50 
 17  terminal types, and each terminal has its own set of options. 
 18   
 19  The strategy here is to define a general mechanism for turning Python 
 20  keyword parameters into fragments of gnuplot command strings.  There 
 21  are a number of classes derived from Arg that do this.  Some take 
 22  string args, some boolean, etc.  Then the list of options that each 
 23  terminal accepts is stored in the terminal_opts dictionary. 
 24  Gnuplot.hardcopy(), in turn, uses this dictionary to interpret its 
 25  keyword arguments and build the 'set terminal' command. 
 26   
 27  """ 
 28   
 29   
 30  import types 
 31   
 32  from . import gp, Errors 
 33   
 34  from PyFoam.ThirdParty.six import string_types 
 35   
36 -class Arg:
37 """Process terminal subargs and return a command fragment. 38 39 Pull one or more arguments from keyw and output a list of strings 40 that will be appended to the 'set terminal' (separated by spaces). 41 Delete any used args from keyw. If no relevant options are found, 42 return None. 43 44 This is a base class for the actual argument-processing classes. 45 Derived classes must define a __call__(self, keyw) method 46 returning a list of strings or None. 47 48 """ 49 50 pass
51 52
53 -class ArgOneParam(Arg):
54 """Arg abstract base class specialized for exactly one parameter. 55 56 Members: 57 58 'argname' -- The name of the keyword argument used to pass 59 this argument to Python. 60 61 'default' -- The default value of the argument, used if no 62 keyword parameter is found. If this is None, then no 63 default is assumed. 64 65 """ 66
67 - def __init__(self, argname, default):
68 self.argname = argname 69 self.default = default
70
71 - def get_option(self, keyw):
72 """Get the keyword argument corresponding to this Arg. 73 74 Look in keyw for the keyword argument needed by this Arg. If 75 it is found, delete it from keyw and return it. If it is not 76 found, return self.default. 77 78 """ 79 80 try: 81 k = keyw[self.argname] 82 except KeyError: 83 return self.default 84 else: 85 del keyw[self.argname] 86 return k
87 88
89 -class KeywordArg(ArgOneParam):
90 """Represent an argument that must be passed as a keyword to gnuplot. 91 92 Some gnuplot options take the form of single unquoted keywords 93 (possibly preceded by a fixed keyword). We allow those to be 94 passed as strings 'option="keyword"'. Check that the option 95 supplied is in the list of allowed options. 96 97 Members: 98 99 'fixedword' -- the fixed keyword that must precede the 100 variable keyword in the gnuplot command, or None if none 101 is required. 102 103 'options' -- a list of strings containing the legal 104 alternatives for this argument. 105 106 """ 107
108 - def __init__(self, argname, options, fixedword=None, default=None):
109 ArgOneParam.__init__(self, argname, default) 110 self.fixedword = fixedword 111 self.options = options
112
113 - def __call__(self, keyw):
114 k = self.get_option(keyw) 115 116 if k is None: 117 return None 118 elif k in self.options: 119 if self.fixedword is None: 120 return [k] 121 else: 122 return [self.fixedword, k] 123 else: 124 raise Errors.OptionError( 125 'Illegal option %s="%s"' % (self.argname, k,))
126 127
128 -class StringArg(ArgOneParam):
129 """An option taking a quoted string argument.""" 130
131 - def __init__(self, argname, fixedword=None, default=None):
132 ArgOneParam.__init__(self, argname, default) 133 self.fixedword = fixedword
134
135 - def __call__(self, keyw):
136 k = self.get_option(keyw) 137 138 if k is None: 139 return None 140 elif not isinstance(k,string_types): 141 raise Errors.OptionError( 142 'Option %s must be a string' % (self.argname,)) 143 else: 144 retval = [] 145 if self.fixedword is not None: 146 retval.append(self.fixedword) 147 retval.append('"%s"' % k) 148 return retval
149 150
151 -class BareStringArg(ArgOneParam):
152 """An arbitrary argument output without quotes. 153 154 The argument can be a string or anything with a str() 155 representation, or a tuple of such things. Thus this can be used 156 for strings (which will be output without quotation marks), 157 integers, floating point arguments, or multiple arguments of the 158 above types (which will be output separated by spaces). No 159 checking is done that the argument is sensible. 160 161 """ 162
163 - def __init__(self, argname, fixedword=None, default=None):
164 ArgOneParam.__init__(self, argname, default) 165 self.fixedword = fixedword
166
167 - def __call__(self, keyw):
168 k = self.get_option(keyw) 169 170 if k is None: 171 return None 172 else: 173 retval = [] 174 if self.fixedword is not None: 175 retval.append(self.fixedword) 176 if type(k) in (tuple,list): 177 for i in k: 178 retval.append(str(i)) 179 else: 180 retval.append(str(k)) 181 return retval
182 183
184 -class BooleanArg(ArgOneParam):
185 """An argument that takes a true/false value. 186 187 The argument should be 0 or 1. The option is output to gnuplot as 188 'trueval' if the argument is true or 'falseval' if the argument is 189 false. Either one can be 'None', in which case nothing is output. 190 'default' should also be 0 or 1. 191 192 """ 193
194 - def __init__(self, argname, trueval, falseval, 195 fixedword=None, default=None):
196 ArgOneParam.__init__(self, argname, default) 197 self.trueval = trueval 198 self.falseval = falseval 199 self.fixedword = fixedword
200
201 - def __call__(self, keyw):
202 k = self.get_option(keyw) 203 if k is None: 204 return None 205 else: 206 retval = [] 207 if self.fixedword is not None: 208 retval.append(self.fixedword) 209 if k: 210 val = self.trueval 211 else: 212 val = self.falseval 213 if val is not None: 214 retval.append(val) 215 return retval
216 217
218 -class MutuallyExclusiveArgs(Arg):
219 """A group of args, of which either zero or one may be set, but not more. 220 221 Members: 222 223 subargs -- a list [('argname', arg), ...] of Arg instances. 224 'argname' is used to identify the corresponding arg in 225 error messages. (The name of the corresponding keyword 226 args is determined internally by each arg.) 227 228 """ 229
230 - def __init__(self, *subargs):
231 self.subargs = list(subargs)
232
233 - def __call__(self, keyw):
234 foundargname = None 235 retval = None 236 for (argname, arg,) in self.subargs: 237 cmd = arg(keyw) 238 if cmd is not None: 239 if foundargname is not None: 240 raise Errors.OptionError( 241 'Arguments %s and %s cannot both be specified' 242 % (foundargname, argname,) 243 ) 244 else: 245 foundargname = argname 246 retval = cmd 247 return retval # might be None
248 249
250 -class KeywordOrBooleanArg(Arg):
251 """Allow a keyword arg to be specified either as a keyword or a boolean. 252 253 This arg type is the most flexible way to allow keyword parameters 254 to be specified. Say there is an option like 'fontsize' that can 255 take the values 'small' or 'large'. This could be represented as 256 257 'KeywordOrBooleanArg(options=["small", "large"], argname="fontsize")' 258 259 In that case, the fontsize could be specified in any of the 260 following ways: 261 262 'g.hardcopy(..., fontsize="small", ...)' 263 'g.hardcopy(..., fontsize="large", ...)' 264 'g.hardcopy(..., small=1, ...)' 265 'g.hardcopy(..., large=1, ...)' 266 267 If 'argname' is set to be 'None', then the first two possibilities 268 are omitted. 269 270 In the special case that there are exactly two alternatives, one 271 can also use: 272 273 'g.hardcopy(..., small=0, ...) # implies fontsize="large"' 274 'g.hardcopy(..., large=0, ...) # implies fontsize="small"' 275 276 Obviously care must be taken to ensure that none of the implied 277 keyword parameter names conflict with one another or with any of 278 the other Args allowed by a function. 279 280 Members: 281 282 'options' -- a list of strings representing allowed keyword 283 values. These options can be used as boolean values in 284 the style 'option=1'. 285 286 'argname' -- the name of the argname for the 'arg=value' style 287 of setting the argument. If 'None', then this style is 288 not allowed. 289 290 'fixedword' -- a fixed keyword that must precede the option, 291 or 'None'. 292 293 'default' -- the default option to set if nothing is set 294 explicitly, or None to leave nothing set in that case. 295 296 """ 297
298 - def __init__(self, options, argname=None, fixedword=None, default=None):
299 self.options = options 300 self.argname = argname 301 self.fixedword = fixedword 302 self.default = default 303 assert self.default is None or self.default in self.options, \ 304 'default must be a valid option'
305
306 - def __call__(self, keyw):
307 if self.argname is not None and self.argname in keyw: 308 k = keyw[self.argname] 309 del keyw[self.argname] 310 if k is None: 311 pass 312 elif k in self.options: 313 # Make sure it isn't contradicted by the corresponding boolean: 314 if k in keyw and not keyw[k]: 315 raise Errors.OptionError( 316 'Arguments %s and %s are contradictory' 317 % (self.argname, k,) 318 ) 319 else: 320 # Store the option into the boolean to be processed below: 321 keyw[k] = 1 322 else: 323 raise Errors.OptionError( 324 'Illegal option %s=%s' % (self.argname, k,)) 325 326 # Now scan the booleans and make sure that at most one is set: 327 option = None 328 for i in range(len(self.options)): 329 k = self.options[i] 330 if k in keyw: 331 newval = keyw[k] 332 del keyw[k] 333 if newval: 334 if option is not None: 335 raise Errors.OptionError( 336 'Arguments %s and %s cannot both be specified' 337 % (option, k,) 338 ) 339 else: 340 option = k 341 else: 342 # newval was false. This is only legal if this 343 # option only has two possible values: 344 if len(self.options) == 2: 345 option = self.options[1 - i] 346 else: 347 pass 348 349 if option is None: 350 if self.default is None: 351 return None 352 else: 353 option = self.default 354 retval = [] 355 if self.fixedword is not None: 356 retval.append(self.fixedword) 357 retval.append(option) 358 return retval
359 360 361 # Now we define the allowed options for a few terminal types. This 362 # table is used by Gnuplot.hardcopy() to construct the necessary 'set 363 # terminal' command. 364 365 terminal_opts = {} 366 367 terminal_opts['postscript'] = [ 368 KeywordOrBooleanArg( 369 options=['landscape', 'portrait', 'eps', 'default'], 370 argname='mode', 371 ), 372 KeywordOrBooleanArg( 373 options=['enhanced', 'noenhanced'], 374 # This default should probably be computed from the *current* 375 # value of GnuplotOpts, not at import time. ### 376 default=(gp.GnuplotOpts.prefer_enhanced_postscript 377 and 'enhanced' 378 or 'noenhanced'), 379 ), 380 KeywordOrBooleanArg(options=['color', 'monochrome']), 381 KeywordOrBooleanArg(options=['solid', 'dashed']), 382 KeywordOrBooleanArg( 383 options=['defaultplex', 'simplex', 'duplex'], 384 argname='duplexing', 385 ), 386 StringArg(argname='fontname'), 387 BareStringArg(argname='fontsize'), 388 ] 389 390 terminal_opts['pdf'] = [ 391 KeywordOrBooleanArg( 392 options=['landscape', 'portrait', 'eps', 'default'], 393 argname='mode', 394 ), 395 KeywordOrBooleanArg(options=['color', 'monochrome']), 396 KeywordOrBooleanArg(options=['solid', 'dashed']), 397 KeywordOrBooleanArg( 398 options=['defaultplex', 'simplex', 'duplex'], 399 argname='duplexing', 400 ), 401 StringArg(argname='fontname'), 402 BareStringArg(argname='fontsize'), 403 ] 404 405 terminal_opts['png'] = [ 406 KeywordOrBooleanArg( 407 options=['small', 'medium', 'large'], 408 argname='fontsize', 409 ), 410 KeywordOrBooleanArg(options=['monochrome', 'gray', 'color']), 411 ] 412 413 terminal_opts['fig'] = [ 414 KeywordOrBooleanArg(options=['monochrome', 'color']), 415 KeywordOrBooleanArg(options=['small', 'big']), 416 BareStringArg(argname='pointsmax', fixedword='pointsmax'), 417 KeywordOrBooleanArg(options=['landscape', 'portrait']), 418 KeywordOrBooleanArg(options=['metric', 'inches']), 419 BareStringArg(argname='fontsize'), 420 BareStringArg(argname='size'), # needs a tuple of two doubles 421 BareStringArg(argname='thickness'), 422 BareStringArg(argname='depth'), 423 ] 424 425 terminal_opts['cgm'] = [ 426 KeywordOrBooleanArg( 427 options=['landscape', 'portrait', 'default'], 428 argname='mode', 429 ), 430 KeywordOrBooleanArg(options=['color', 'monochrome']), 431 KeywordOrBooleanArg(options=['rotate', 'norotate']), 432 BareStringArg(argname='width', fixedword='width'), 433 BareStringArg(argname='linewidth', fixedword='linewidth'), 434 StringArg(argname='font'), 435 BareStringArg(argname='fontsize'), 436 ] 437 438 terminal_opts['pict'] = [ 439 KeywordOrBooleanArg( 440 options=['landscape', 'portrait', 'default'], 441 argname='mode', 442 ), 443 KeywordOrBooleanArg(options=['color', 'monochrome']), 444 KeywordOrBooleanArg(options=['dashes', 'nodashes']), 445 446 # default font, which must be a valid pict font: 447 StringArg(argname='fontname'), 448 449 # default font size, in points: 450 BareStringArg(argname='fontsize'), 451 452 # width of plot in pixels: 453 BareStringArg(argname='width'), 454 455 # height of plot in pixels: 456 BareStringArg(argname='height'), 457 458 ] 459 460 terminal_opts['mp'] = [ 461 KeywordOrBooleanArg(options=['color', 'colour', 'monochrome']), 462 KeywordOrBooleanArg(options=['solid', 'dashed']), 463 KeywordOrBooleanArg(options=['notex', 'tex', 'latex']), 464 BareStringArg(argname='magnification'), 465 KeywordOrBooleanArg(options=['psnfss', 'psnfss-version7', 'nopsnfss']), 466 BareStringArg(argname='prologues'), 467 KeywordOrBooleanArg(options=['a4paper']), 468 KeywordOrBooleanArg(options=['amstex']), 469 StringArg(argname='fontname'), 470 BareStringArg(argname='fontsize'), 471 ] 472 473 terminal_opts['svg'] = [ 474 BareStringArg(argname='size', fixedword='size'), # tuple of two doubles 475 KeywordOrBooleanArg(options=['fixed', 'dynamic']), 476 StringArg(argname='fname', fixedword='fname'), 477 BareStringArg(argname='fsize', fixedword='fsize'), 478 KeywordOrBooleanArg(options=['enhanced', 'noenhanced']), 479 StringArg(argname='fontfile', fixedword='fontfile'), 480 ] 481 482 # Should work with Python3 and Python2 483