-
Notifications
You must be signed in to change notification settings - Fork 3
/
scripting_guidelines.html
535 lines (498 loc) · 52.6 KB
/
scripting_guidelines.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Scripting guidelines — PyCogent 1.9 documentation</title>
<link rel="stylesheet" href="_static/agogo.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '1.9',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true
};
</script>
<script type="text/javascript" src="_static/jquery.js"></script>
<script type="text/javascript" src="_static/underscore.js"></script>
<script type="text/javascript" src="_static/doctools.js"></script>
<link rel="top" title="PyCogent 1.9 documentation" href="index.html" />
<link rel="next" title="Licenses and disclaimer" href="licenses.html" />
<link rel="prev" title="For Developers" href="developer_notes.html" />
<script type="text/javascript" src="http://www.google.com/jsapi?key=ABQIAAAAbW_pA971hrPgosv-Msv7hRQZ4X-jPDmWcshBrz2j7-fJvuUABRTGWmdiw2G89JpgztGlFGG8hDxRAw"></script>\
<script type="text/javascript" src="_static/google_feed.js"></script>
</head>
<body role="document">
<div class="header-wrapper" role="banner">
<div class="header">
<div class="headertitle"><a
href="index.html">PyCogent 1.9 documentation</a></div>
<div class="rel" role="navigation" aria-label="related navigation">
<a href="developer_notes.html" title="For Developers"
accesskey="P">previous</a> |
<a href="licenses.html" title="Licenses and disclaimer"
accesskey="N">next</a> |
<a href="genindex.html" title="General Index"
accesskey="I">index</a>
</div>
</div>
</div>
<div class="content-wrapper">
<div class="content">
<div class="document">
<div class="documentwrapper">
<div class="bodywrapper">
<div class="body" role="main">
<div class="section" id="scripting-guidelines">
<h1>Scripting guidelines<a class="headerlink" href="#scripting-guidelines" title="Permalink to this headline">¶</a></h1>
<p>Developing command line interfaces for your scripts is a convenient way to create easily reproducible analyses with PyCogent. This document covers the support for developing standardized interfaces in PyCogent. In addition to making your code easier to distribute (or to return to months after it was originally written), several GUI generators that are currently in development make use of the PyCogent <code class="docutils literal"><span class="pre">option_parsing</span></code> module – this means that defining your interfaces with PyCogent’s <code class="docutils literal"><span class="pre">option_parsing</span></code> module will allow your code to be easily wrapped in graphical interfaces.</p>
<p>PyCogent command line interfaces are based on the <code class="docutils literal"><span class="pre">optparse</span></code> module in the Python Standard Library, using <code class="docutils literal"><span class="pre">cogent.util.option_parsing.parse_command_line_parameters</span></code> as a convenience wrapper for defining interfaces based on certain information provided by the script developer. A fully functional example script <a class="reference internal" href="#countseqs"><span class="std std-ref">Example of a simple PyCogent script</span></a> and a script template <a class="reference internal" href="#scripttemplate"><span class="std std-ref">Template for a new PyCogent script</span></a> are provided below.</p>
<p>This page will help you develop your command line interfaces after you’ve familiarized yourself with <code class="docutils literal"><span class="pre">optparse</span></code>, but will not be a replacement to a general understanding of how to interact with <code class="docutils literal"><span class="pre">optparse</span></code>. You should therefore refer both to the <a class="reference external" href="http://docs.python.org/library/optparse.html">optparse documentation</a> as well as these PyCogent Scripting Guidelines. As support for optparse will not continue into Python 3.0, we will be switching to <code class="docutils literal"><span class="pre">argparse</span></code> when we transition PyCogent to Python 3. We’ll do our best to minimize the work in transitioning from <code class="docutils literal"><span class="pre">optparse</span></code> to <code class="docutils literal"><span class="pre">argparse</span></code> for PyCogent scripts by changing the interface to <code class="docutils literal"><span class="pre">cogent.util.option_parsing.parse_command_line_parameters</span></code> as little as possible.</p>
<p>This document starts with a basic example of creating a script. It then covers guidelines for defining scripts which all PyCogent developers must adhere to, and which we suggest all PyCogent script developers adhere to. Finally it covers some details of the <code class="docutils literal"><span class="pre">script_info</span></code> object and custom command line option types defined in PyCogent.</p>
<p>You should also review the PyCogent <a class="reference internal" href="coding_guidelines.html#coding-guidelines"><span class="std std-ref">Coding guidelines</span></a>. The scripting guidelines presented here are an extension of those.</p>
<div class="section" id="quickstart-how-to-create-your-first-pycogent-script-in-5-minutes">
<h2>Quickstart : how to create your first PyCogent script in 5 minutes<a class="headerlink" href="#quickstart-how-to-create-your-first-pycogent-script-in-5-minutes" title="Permalink to this headline">¶</a></h2>
<p>These steps show you how to quickly create a working PyCogent script from the PyCogent script template. Some very basic familiarity with python will help here (e.g., identifying the <code class="docutils literal"><span class="pre">main()</span></code> function and adding to it with the correct indentation).</p>
<ol class="arabic">
<li><p class="first">Copy and paste the script template <a class="reference internal" href="#scripttemplate"><span class="std std-ref">Template for a new PyCogent script</span></a> to a new file on your system. The next steps will assume that you’re saving that file as <code class="docutils literal"><span class="pre">/path/to/home/pycogent_user/pycogent_script_template.py</span></code>.</p>
</li>
<li><p class="first">Open a command terminal and enter the following command:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">chmod</span> <span class="mi">755</span> <span class="o">/</span><span class="n">path</span><span class="o">/</span><span class="n">to</span><span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">pycogent_user</span><span class="o">/</span><span class="n">pycogent_script_template</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
</li>
<li><p class="first">Open <code class="docutils literal"><span class="pre">pycogent_script_template.py</span></code> with a text editor (such as emacs, pico, or TextWrangler) and add the following to the bottom of the main() function (be sure you have proper indentation):</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="nb">print</span> <span class="s2">"Hello World!"</span>
</pre></div>
</div>
</li>
</ol>
<p>Next, after the line:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">script_info</span><span class="p">[</span><span class="s1">'version'</span><span class="p">]</span> <span class="o">=</span> <span class="n">__version__</span>
</pre></div>
</div>
<p>add the following line:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">script_info</span><span class="p">[</span><span class="s1">'help_on_no_arguments'</span><span class="p">]</span> <span class="o">=</span> <span class="kc">False</span>
</pre></div>
</div>
<ol class="arabic" start="4">
<li><p class="first">Run and print help text:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">pycogent_user</span><span class="o">/</span><span class="n">pycogent_script_template</span><span class="o">.</span><span class="n">py</span> <span class="o">-</span><span class="n">h</span>
</pre></div>
</div>
</li>
<li><p class="first">Run script – <code class="docutils literal"><span class="pre">Hello</span> <span class="pre">World!</span></code> will be printed to the terminal:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="o">/</span><span class="n">home</span><span class="o">/</span><span class="n">pycogent_user</span><span class="o">/</span><span class="n">pycogent_script_template</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
</li>
</ol>
<p>You’ve now got a working PyCogent script. You can continue working with this script to add the functionality you’re interested in. See the <a class="reference external" href="http://docs.python.org/library/optparse.html">optparse documentation</a> documentation for discussion of how to create options, as well as the example script <a class="reference internal" href="#countseqs"><span class="std std-ref">Example of a simple PyCogent script</span></a> provided below.</p>
</div>
<div class="section" id="general-notes-on-designing-command-line-interfaces">
<h2>General notes on designing command line interfaces<a class="headerlink" href="#general-notes-on-designing-command-line-interfaces" title="Permalink to this headline">¶</a></h2>
<p><strong>Design convenient command line interfaces.</strong> The goal of your interface is to make things easy for the user (who is often you). This section covers some guidelines for how to do that.</p>
<p><strong>Have people who are better programmers than you interact with your command line interface and give you feedback on it.</strong> If your script is difficult to work with, or has requirements that are not intuitive for users who frequently work with command line applications, people won’t use your code.</p>
<p><strong>If there are tasks that are automatable, automate them.</strong> For example, if you can make a good guess at what an output file should be named from an input file and a parameter choice, do that and use it as the default output path (but allow the user to overwrite it with a command line option).</p>
<p><strong>Define sensible default values for your command line options.</strong> If most of the time that a script is used it will require a parameter to be set to a certain value, make that value the default to simplify the interface.</p>
<p><strong>Have the user specify named options rather than positional arguments.</strong> The latter are more difficult to work with as users need to remember the order that they need to be passed. PyCogent scripts do not allow positional arguments by default, but if you must use them you can override this behavior by setting <code class="docutils literal"><span class="pre">script_info['disallow_positional_arguments']</span> <span class="pre">=</span> <span class="pre">False</span></code>. Note that this contradicts what the <code class="docutils literal"><span class="pre">optparse</span></code> docs say - we disagree with their comment that all required options should be passed as positional arguments.</p>
<p><strong>Avoid making assumptions about how a script will be run.</strong> Perhaps most importantly, don’t assume that the script will be run from the same directory that the script lives in. Users often want to copy executables into a centralized directory on their system (e.g., <code class="docutils literal"><span class="pre">/usr/local/bin</span></code>). Facilitate that by not requiring that the script is run from a specific location. If you rely on data files, you have other options such as having users set an environment variable that defines where data files live on the system. Test your script from multiple locations on the file system!</p>
</div>
<div class="section" id="designing-pycogent-command-line-interfaces">
<h2>Designing PyCogent command line interfaces<a class="headerlink" href="#designing-pycogent-command-line-interfaces" title="Permalink to this headline">¶</a></h2>
<p>This section covers guidelines for how to build PyCogent command line interfaces using the <code class="docutils literal"><span class="pre">script_info</span></code> dictionary and the <code class="docutils literal"><span class="pre">cogent.util.option_parsing.parse_command_line_parameters</span></code> function. Some of this is general to <code class="docutils literal"><span class="pre">optparse</span></code> and some is specific to PyCogent.</p>
<div class="section" id="flag-options">
<h3>Flag options<a class="headerlink" href="#flag-options" title="Permalink to this headline">¶</a></h3>
<p>Flags are boolean options to your script. <code class="docutils literal"><span class="pre">optparse</span></code> supports these directly, so you should never have to define an option that explicitly takes <code class="docutils literal"><span class="pre">True</span></code> or <code class="docutils literal"><span class="pre">False</span></code> on the command line.</p>
<p>Flags to your script should always be either <code class="docutils literal"><span class="pre">action='store_true'</span></code> or <code class="docutils literal"><span class="pre">action='store_false'</span></code>, and do not need to define a type. The names of these options should suggest whether the option enables something (e.g., <code class="docutils literal"><span class="pre">--print_to_stdout</span></code>) which would be defined with <code class="docutils literal"><span class="pre">action='store_true'</span></code> (i.e., default is False), or whether the option disables something (e.g., <code class="docutils literal"><span class="pre">--suppress_stdout</span></code>) which would be defined with <code class="docutils literal"><span class="pre">action='store_false'</span></code> (i.e., the default is True). A bad name for a flag is <code class="docutils literal"><span class="pre">--stdout</span></code> as it’s not clear what this option does.</p>
<p>Always define <code class="docutils literal"><span class="pre">default</span></code> for boolean options to set the default option for your script. If <code class="docutils literal"><span class="pre">action='store_true'</span></code> you should <em>always</em> pass <code class="docutils literal"><span class="pre">default=False</span></code>. If <code class="docutils literal"><span class="pre">action='store_false'</span></code> you should <em>always</em> pass <code class="docutils literal"><span class="pre">default=True</span></code>.</p>
</div>
<div class="section" id="choice-options">
<h3>Choice options<a class="headerlink" href="#choice-options" title="Permalink to this headline">¶</a></h3>
<p>Use <code class="docutils literal"><span class="pre">type=choice</span></code> when an option is passed as a string and can be one of several acceptable values. This saves you from having to check that the user passed an acceptable value. This is done by <code class="docutils literal"><span class="pre">optparse</span></code>, so saves you lines of code that you’d need to test, and standardizes how errors are handled. The acceptable choices are defined with <code class="docutils literal"><span class="pre">choices=</span></code>. An example choice option definition is:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">alignment_method_choices</span> <span class="o">=</span> <span class="p">[</span><span class="s1">'pynast'</span><span class="p">,</span><span class="s1">'mafft'</span><span class="p">,</span><span class="s1">'muscle'</span><span class="p">]</span>
<span class="n">o</span> <span class="o">=</span> <span class="n">make_option</span><span class="p">(</span><span class="s1">'-m'</span><span class="p">,</span><span class="s1">'--alignment_method'</span><span class="p">,</span><span class="nb">type</span><span class="o">=</span><span class="s1">'choice'</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s1">'Method for aligning sequences. Valid choices are: '</span><span class="o">+</span>\
<span class="s1">', '</span><span class="o">.</span><span class="n">join</span><span class="p">(</span><span class="n">alignment_method_choices</span><span class="p">)</span> <span class="o">+</span> <span class="s1">' [default: </span><span class="si">%d</span><span class="s1">efault]'</span><span class="p">,</span>
<span class="n">choices</span><span class="o">=</span><span class="n">alignment_method_choices</span><span class="p">,</span> <span class="n">default</span><span class="o">=</span><span class="s1">'pynast'</span><span class="p">)</span>
</pre></div>
</div>
<p>Note that the help text here includes the list of acceptable options. This is generally a good idea as it’s convenient for the user. It’s not a good idea however if this is a big list (say, more than 5 or so options). If the user passes something invalid (such as <code class="docutils literal"><span class="pre">raxml</span></code> in this example) the list of acceptable options will be included in the error text.</p>
</div>
<div class="section" id="defining-where-output-will-be-stored">
<h3>Defining where output will be stored<a class="headerlink" href="#defining-where-output-will-be-stored" title="Permalink to this headline">¶</a></h3>
<p>If a single file is created, allow the user to define that file name. If multiple files are created, allow the user to define a directory name and store all of the output files in that directory. Use the <code class="docutils literal"><span class="pre">new_filepath</span></code> and <code class="docutils literal"><span class="pre">new_dirpath</span></code>, respectively, to define these output types. These will raise errors if the file or directory already exists, which is generally good as it avoids overwriting results that may have taken a long time to generate.</p>
</div>
</div>
<div class="section" id="defining-options">
<h2>Defining options<a class="headerlink" href="#defining-options" title="Permalink to this headline">¶</a></h2>
<p>Use <code class="docutils literal"><span class="pre">make_option</span></code> (<a class="reference external" href="http://docs.python.org/library/optparse.html#populating-the-parser">described here</a>) to create options. As in that example, you’ll define these in lists that get set as <code class="docutils literal"><span class="pre">script_info['required_options']</span></code> and <code class="docutils literal"><span class="pre">script_info['optional_options']</span></code>.</p>
<p>Use the PyCogent custom option types when specifying input file or directory paths. These standardize error handling in the case of input files which don’t exist or aren’t readable and output files which already exist.</p>
<p>Don’t define <code class="docutils literal"><span class="pre">dest=</span></code>. By default this gets set to the long-form parameter option (e.g. <code class="docutils literal"><span class="pre">dest='input_fp'</span></code> is implied if your option is <code class="docutils literal"><span class="pre">--input_fp</span></code>). Defining this as something else will confuse other people who may end up doing maintenance work on your scripts in the future.</p>
<p>Always define <code class="docutils literal"><span class="pre">default=</span></code> for optional options, and never define <code class="docutils literal"><span class="pre">default=</span></code> for required options. The default value for all options is <code class="docutils literal"><span class="pre">None</span></code>, but it’s convenient to explicitly define that for readability.</p>
<p>Always define <code class="docutils literal"><span class="pre">help=</span></code>, and provide useful information in this string. Include <code class="docutils literal"><span class="pre">[default:</span> <span class="pre">%default]</span></code> for optional options, but not for required options (as there can be no default for a required option, or it’d be optional). The <code class="docutils literal"><span class="pre">%default</span></code> gets replaced with the value provided for <code class="docutils literal"><span class="pre">default=</span></code>. It sometimes makes sense to include additional information in the <code class="docutils literal"><span class="pre">[default:%default]</span></code> text if the option on it’s own is not informative. For example:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">make_option</span><span class="p">(</span><span class="s2">"--output_fp"</span><span class="p">,</span><span class="n">default</span><span class="o">=</span><span class="kc">None</span><span class="p">,</span><span class="n">help</span><span class="o">=</span><span class="s2">"output filepath [default:</span><span class="si">%d</span><span class="s2">efault; print to stdout]"</span><span class="p">)</span>
</pre></div>
</div>
<p><code class="docutils literal"><span class="pre">action=store</span></code> and <code class="docutils literal"><span class="pre">type=string</span></code> are defaults, and therefore do not need to be included. Leave these values out to keep your code cleaner.</p>
<p>If you need to pass multiple paths or strings to a single option, do this by passing a comma-separated string. The <code class="docutils literal"><span class="pre">existing_filepaths</span></code> option type expects strings in this format and takes care of splitting them on commas and returning a list, so if you’re passing multiple input filepaths set <code class="docutils literal"><span class="pre">type='existing_filepaths'</span></code>.</p>
</div>
<div class="section" id="naming-options">
<h2>Naming options<a class="headerlink" href="#naming-options" title="Permalink to this headline">¶</a></h2>
<p><code class="docutils literal"><span class="pre">optparse</span></code> allows for users to define short-form (e.g., <code class="docutils literal"><span class="pre">-i</span></code>) and long-form (<code class="docutils literal"><span class="pre">--input_fp</span></code>) option names. For options that are commonly used, define both a long-form and a short-form parameter name:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">make_option</span><span class="p">(</span><span class="s1">'-i'</span><span class="p">,</span><span class="s1">'--input_dir'</span><span class="p">,</span><span class="nb">type</span><span class="o">=</span><span class="s2">"existing_filepath"</span><span class="p">,</span><span class="n">help</span><span class="o">=</span><span class="s1">'the input directory'</span><span class="p">)</span>
</pre></div>
</div>
<p>For options that are infrequently used define only a long-form parameter name:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">make_option</span><span class="p">(</span><span class="s1">'--output_file_type'</span><span class="p">,</span><span class="n">help</span><span class="o">=</span><span class="s1">'the file type for graphical output'</span><span class="p">,</span><span class="n">default</span><span class="o">=</span><span class="s1">'pdf'</span><span class="p">)</span>
</pre></div>
</div>
<p>This helps with reducing clutter and saving convenient short-form parameter names for future options that may be added.</p>
<p>Make paths to files end with <code class="docutils literal"><span class="pre">_fp</span></code> and paths to directories end with <code class="docutils literal"><span class="pre">_dir</span></code>. This helps users understand exactly what must be passed to a script.</p>
<p>Some standard names for common options are listed below. You should use these whenever possible.</p>
<table border="1" class="docutils">
<colgroup>
<col width="24%" />
<col width="76%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">Description</th>
<th class="head">Option name</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>path to an input file</td>
<td><code class="docutils literal"><span class="pre">-i</span></code>, <code class="docutils literal"><span class="pre">--input_fp</span></code></td>
</tr>
<tr class="row-odd"><td>path to an output file</td>
<td><code class="docutils literal"><span class="pre">-o</span></code>, <code class="docutils literal"><span class="pre">--output_fp</span></code></td>
</tr>
<tr class="row-even"><td>path to an input directory</td>
<td><code class="docutils literal"><span class="pre">-i</span></code>, <code class="docutils literal"><span class="pre">--input_dir</span></code></td>
</tr>
<tr class="row-odd"><td>path to an output dir</td>
<td><code class="docutils literal"><span class="pre">-o</span></code>, <code class="docutils literal"><span class="pre">--output_dir</span></code></td>
</tr>
<tr class="row-even"><td>path to a log file</td>
<td><code class="docutils literal"><span class="pre">-l</span></code>, <code class="docutils literal"><span class="pre">--log_fp</span></code></td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="what-documentation-should-be-included-in-my-scripts">
<h2>What documentation should be included in my scripts?<a class="headerlink" href="#what-documentation-should-be-included-in-my-scripts" title="Permalink to this headline">¶</a></h2>
<p>The <code class="docutils literal"><span class="pre">script_documentation</span></code> entry in <code class="docutils literal"><span class="pre">script_info</span></code> should describe the basic functionality of your script. This entry is typically one to several sentences. Be sure not to add line breaks yourself - <code class="docutils literal"><span class="pre">optparse</span></code> will take care of this for you, and the formatting will look better than if you try to do it yourself.</p>
<p>The <code class="docutils literal"><span class="pre">usage_examples</span></code> entry in <code class="docutils literal"><span class="pre">script_info</span></code> should list one or more examples of commands that need to be run to execute your script. These should be actual calls to commands. A user should be able to copy this and paste it on the command line and have the script run (provided they put the right input files in place). See the example script <a class="reference internal" href="#countseqs"><span class="std std-ref">Example of a simple PyCogent script</span></a> for instances of what good usage examples look like. <code class="docutils literal"><span class="pre">script_info['usage_examples']</span></code> must be a list of tuples with three string entries each where the first entry is a concise title for the example, the second entry is a description of the example and why certain parameter settings are being made, and the third entry should be the exact command that needs to be run. Start these examples with <code class="docutils literal"><span class="pre">%prog</span></code> - this gets replaced with the name of your script and is convenient so you don’t have to remember to update the usage examples if the name of your script changes.</p>
<p>The <code class="docutils literal"><span class="pre">output_description</span></code> entry in <code class="docutils literal"><span class="pre">script_info</span></code> should describe the output generated by the script. This entry is typically one to several sentences. Again, don’t add line breaks yourself.</p>
</div>
<div class="section" id="the-script-info-dictionary">
<h2>The script_info dictionary<a class="headerlink" href="#the-script-info-dictionary" title="Permalink to this headline">¶</a></h2>
<p>The <code class="docutils literal"><span class="pre">script_info</span></code> dictionary is the central piece of information required to define a cogent script. <code class="docutils literal"><span class="pre">script_info</span></code> is passed to <code class="docutils literal"><span class="pre">parse_command_line_parameters</span></code> to define the command line interface for your script. Additionally several tools have been developed to import and use this object to define other types of interfaces (e.g., script form in the PyCogent beta GUI) or to auto-generate script documentation (e.g., for the QIIME project). This section covers the values that can be defined in your <code class="docutils literal"><span class="pre">script_info</span></code> dictionaries, what they do, and their default values.</p>
<div class="section" id="core-values-defined-in-pycogent-command-line-interfaces">
<h3>Core values defined in PyCogent command line interfaces<a class="headerlink" href="#core-values-defined-in-pycogent-command-line-interfaces" title="Permalink to this headline">¶</a></h3>
<p>These are the core values defined in the <code class="docutils literal"><span class="pre">script_info</span></code> dictionary used by the PyCogent <code class="docutils literal"><span class="pre">option_parsing</span></code> module.</p>
<table border="1" class="docutils">
<colgroup>
<col width="21%" />
<col width="69%" />
<col width="10%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">key</th>
<th class="head">Description</th>
<th class="head">Default</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>script_description</td>
<td>a paragraph description of the script’s functionality</td>
<td>REQUIRED</td>
</tr>
<tr class="row-odd"><td>script_usage</td>
<td>a list of tuples illustrating example usages of the script</td>
<td>[]</td>
</tr>
<tr class="row-even"><td>output_description</td>
<td>a paragraph description of the script’s output</td>
<td>“”</td>
</tr>
<tr class="row-odd"><td>version</td>
<td>a version number for the script</td>
<td>REQUIRED</td>
</tr>
<tr class="row-even"><td>required_options</td>
<td>a list of optparse Option objects that are required for the script to run</td>
<td>[]</td>
</tr>
<tr class="row-odd"><td>optional_options</td>
<td>a list of optparse Option objects that are optional for the script to run</td>
<td>[]</td>
</tr>
<tr class="row-even"><td>disallow_positional_arguments</td>
<td>do not allow positional arguments to be passed to the script</td>
<td>True</td>
</tr>
<tr class="row-odd"><td>help_on_no_arguments</td>
<td>print help text if the script is called with no options or arguments</td>
<td>True</td>
</tr>
<tr class="row-even"><td>suppress_verbose</td>
<td>do not auto-generate a verbose option for the script</td>
<td>False</td>
</tr>
</tbody>
</table>
</div>
<div class="section" id="values-known-to-be-used-by-the-tools-outside-of-the-pycogent-codebase">
<h3>Values known to be used by the tools outside of the PyCogent codebase<a class="headerlink" href="#values-known-to-be-used-by-the-tools-outside-of-the-pycogent-codebase" title="Permalink to this headline">¶</a></h3>
<p>These values are known to be used by tools outside of the PyCogent code base in <code class="docutils literal"><span class="pre">script_info</span></code> objects. It’s best to not name new values with these names to avoid conflicts.</p>
<table border="1" class="docutils">
<colgroup>
<col width="21%" />
<col width="70%" />
<col width="9%" />
</colgroup>
<thead valign="bottom">
<tr class="row-odd"><th class="head">key</th>
<th class="head">Description</th>
<th class="head">Used by</th>
</tr>
</thead>
<tbody valign="top">
<tr class="row-even"><td>brief_description</td>
<td>a one-sentence description of the script, used by some document generators</td>
<td>Q,T</td>
</tr>
<tr class="row-odd"><td>script_type</td>
<td>a definition of the type of script, used by some graphical interfaces</td>
<td>Q,PG</td>
</tr>
<tr class="row-even"><td>optional_options_groups</td>
<td>a list grouping related options under a heading [[‘section heading string’, section_option_list], ...]</td>
<td>PG</td>
</tr>
<tr class="row-odd"><td>authors</td>
<td>string of author names</td>
<td>PG</td>
</tr>
<tr class="row-even"><td>script_name</td>
<td>a brief “human readable” name for the script, used in some graphical interfaces</td>
<td>Q,PG</td>
</tr>
<tr class="row-odd"><td>output_type</td>
<td>a list of tuples noting the type (in a controlled vocabulary) of each possible output</td>
<td>Q</td>
</tr>
<tr class="row-even"><td>option_label</td>
<td>a dictionary matching option names to “human readable” names, used in some graphical interfaces</td>
<td>Q</td>
</tr>
<tr class="row-odd"><td>script_usage_output_to_remove</td>
<td>a list of output dirs/files that must be cleaned up if running script_usage examples multiple times</td>
<td>Q</td>
</tr>
</tbody>
</table>
<ul class="simple">
<li>“Used by” key : Q: <a class="reference external" href="http://www.qiime.org">QIIME</a>; PG: PyCogent beta GUI; T: tax2tree.</li>
</ul>
</div>
<div class="section" id="setting-values-in-script-info">
<h3>Setting values in script_info<a class="headerlink" href="#setting-values-in-script-info" title="Permalink to this headline">¶</a></h3>
<p>The <code class="docutils literal"><span class="pre">script_info</span></code> object is simply a dict, so the standard method for setting and working with dict entries applies. Some examples are:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">script_info</span><span class="p">[</span><span class="s1">'brief_description'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"Count sequences in one or more fasta files."</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'required_options'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">make_option</span><span class="p">(</span><span class="s1">'-i'</span><span class="p">,</span><span class="s1">'--input_fps'</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s1">'the input filepaths (comma-separated)'</span><span class="p">),</span>
<span class="p">]</span>
</pre></div>
</div>
</div>
</div>
<div class="section" id="custom-command-line-option-types">
<h2>Custom command line option types<a class="headerlink" href="#custom-command-line-option-types" title="Permalink to this headline">¶</a></h2>
<p>Several custom option types are defined in PyCogent. These are:</p>
<ul class="simple">
<li><code class="docutils literal"><span class="pre">existing_path</span></code> : Specify a path to a directory or file. Path must exist or an error is raised.</li>
<li><code class="docutils literal"><span class="pre">new_path</span></code> : Specify a path to a directory or file. Path must not exist or an error is raised.</li>
<li><code class="docutils literal"><span class="pre">existing_filepath</span></code> : Specify a path to a file. Path must exist or an error is raised.</li>
<li><code class="docutils literal"><span class="pre">existing_filepaths</span></code> : Specify a comma-separated list of file paths. All paths must exist or an error is raised. These are returned as a list split on commas.</li>
<li><code class="docutils literal"><span class="pre">new_filepath</span></code> : Specify a path to a file. Path must not exist or an error is raised.</li>
<li><code class="docutils literal"><span class="pre">existing_dirpath</span></code> : Specify a path to a directory. Path must exist or an error is raised.</li>
<li><code class="docutils literal"><span class="pre">new_dirpath</span></code> : Specify a path to a directory. Path must not exist or an error is raised.</li>
</ul>
</div>
<div class="section" id="template-for-a-new-pycogent-script">
<span id="scripttemplate"></span><h2>Template for a new PyCogent script<a class="headerlink" href="#template-for-a-new-pycogent-script" title="Permalink to this headline">¶</a></h2>
<p>The following is a template for a PyCogent script. You can download this from <a class="reference download internal" href="_downloads/pycogent_script_template.py" download=""><code class="xref download docutils literal"><span class="pre">here</span></code></a> to form the basis of your new script. This script is also embedded here for documentation purposes. This template forms a fully functional PyCogent script, so on copying this you should be able to run the script to confirm that it is working:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="n">python</span> <span class="n">pycogent_script_template</span><span class="o">.</span><span class="n">py</span>
</pre></div>
</div>
<p>This will print help text and exit.</p>
<p>You can rename this script and use it define your new PyCogent script.</p>
<p>PyCogent script template:</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python</span>
<span class="c1"># File created on 15 Jul 2011</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">division</span>
<span class="n">__author__</span> <span class="o">=</span> <span class="s2">"AUTHOR_NAME"</span>
<span class="n">__copyright__</span> <span class="o">=</span> <span class="s2">"COPYRIGHT_INFORMATION"</span>
<span class="n">__credits__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"AUTHOR_NAME"</span><span class="p">]</span>
<span class="n">__license__</span> <span class="o">=</span> <span class="s2">"GPL"</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s2">"1.6.0dev"</span>
<span class="n">__maintainer__</span> <span class="o">=</span> <span class="s2">"AUTHOR_NAME"</span>
<span class="n">__email__</span> <span class="o">=</span> <span class="s2">"AUTHOR_EMAIL"</span>
<span class="n">__status__</span> <span class="o">=</span> <span class="s2">"Development"</span>
<span class="kn">from</span> <span class="nn">cogent.util.option_parsing</span> <span class="k">import</span> <span class="n">parse_command_line_parameters</span><span class="p">,</span> <span class="n">make_option</span>
<span class="n">script_info</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'brief_description'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">""</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'script_description'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">""</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'script_usage'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[(</span><span class="s2">""</span><span class="p">,</span><span class="s2">""</span><span class="p">,</span><span class="s2">""</span><span class="p">)]</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'output_description'</span><span class="p">]</span><span class="o">=</span> <span class="s2">""</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'required_options'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span>\
<span class="c1"># Example required option</span>
<span class="c1">#make_option('-i','--input_dir',type="existing_filepath",help='the input directory'),\</span>
<span class="p">]</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'optional_options'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span>\
<span class="c1"># Example optional option</span>
<span class="c1">#make_option('-o','--output_dir',type="new_dirpath",help='the output directory [default: %default]'),\</span>
<span class="p">]</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'version'</span><span class="p">]</span> <span class="o">=</span> <span class="n">__version__</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">option_parser</span><span class="p">,</span> <span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span>\
<span class="n">parse_command_line_parameters</span><span class="p">(</span><span class="o">**</span><span class="n">script_info</span><span class="p">)</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
</div>
<div class="section" id="example-of-a-simple-pycogent-script">
<span id="countseqs"></span><h2>Example of a simple PyCogent script<a class="headerlink" href="#example-of-a-simple-pycogent-script" title="Permalink to this headline">¶</a></h2>
<p>You can download an example PyCogent script for counting the number of sequences in one or more fasta files <a class="reference download internal" href="_downloads/count_seqs.py" download=""><code class="xref download docutils literal"><span class="pre">here</span></code></a>. This script is also embedded here for documentation purposes.</p>
<div class="highlight-default"><div class="highlight"><pre><span></span><span class="ch">#!/usr/bin/env python</span>
<span class="kn">from</span> <span class="nn">__future__</span> <span class="k">import</span> <span class="n">division</span>
<span class="n">__author__</span> <span class="o">=</span> <span class="s2">"Greg Caporaso"</span>
<span class="n">__copyright__</span> <span class="o">=</span> <span class="s2">"Copyright 2011, The PyCogent project"</span>
<span class="n">__credits__</span> <span class="o">=</span> <span class="p">[</span><span class="s2">"Greg Caporaso"</span><span class="p">]</span>
<span class="n">__license__</span> <span class="o">=</span> <span class="s2">"GPL"</span>
<span class="n">__version__</span> <span class="o">=</span> <span class="s2">"1.6.0dev"</span>
<span class="n">__maintainer__</span> <span class="o">=</span> <span class="s2">"Greg Caporaso"</span>
<span class="n">__email__</span> <span class="o">=</span> <span class="s2">"[email protected]"</span>
<span class="n">__status__</span> <span class="o">=</span> <span class="s2">"Development"</span>
<span class="kn">from</span> <span class="nn">glob</span> <span class="k">import</span> <span class="n">glob</span>
<span class="kn">from</span> <span class="nn">cogent.util.option_parsing</span> <span class="k">import</span> <span class="p">(</span>
<span class="n">parse_command_line_parameters</span><span class="p">,</span>
<span class="n">make_option</span><span class="p">)</span>
<span class="kn">from</span> <span class="nn">cogent.parse.fasta</span> <span class="k">import</span> <span class="n">MinimalFastaParser</span>
<span class="n">script_info</span> <span class="o">=</span> <span class="p">{}</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'brief_description'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"Count sequences in one or more fasta files."</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'script_description'</span><span class="p">]</span> <span class="o">=</span> <span class="s2">"This script counts the number of sequences in one or more fasta files and prints the results to stdout."</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'script_usage'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span>\
<span class="p">(</span><span class="s2">"Count sequences in one file"</span><span class="p">,</span>
<span class="s2">"Count the sequences in a fasta file and write results to stdout."</span><span class="p">,</span>
<span class="s2">"%prog -i in.fasta"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"Count sequences in two file"</span><span class="p">,</span>
<span class="s2">"Count the sequences in two fasta files and write results to stdout."</span><span class="p">,</span>
<span class="s2">"%prog -i in1.fasta,in2.fasta"</span><span class="p">),</span>
<span class="p">(</span><span class="s2">"Count the sequences in many fasta files"</span><span class="p">,</span>
<span class="s2">"Count the sequences all .fasta files in current directory and write results to stdout. Note that -i option must be quoted."</span><span class="p">,</span>
<span class="s2">"%prog -i </span><span class="se">\"</span><span class="s2">*.fasta</span><span class="se">\"</span><span class="s2">"</span><span class="p">)]</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'output_description'</span><span class="p">]</span><span class="o">=</span> <span class="s2">"Tabular data is written to stdout."</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'required_options'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">make_option</span><span class="p">(</span><span class="s1">'-i'</span><span class="p">,</span><span class="s1">'--input_fps'</span><span class="p">,</span>
<span class="n">help</span><span class="o">=</span><span class="s1">'the input filepaths (comma-separated)'</span><span class="p">),</span>
<span class="p">]</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'optional_options'</span><span class="p">]</span> <span class="o">=</span> <span class="p">[</span>
<span class="n">make_option</span><span class="p">(</span><span class="s1">'--suppress_errors'</span><span class="p">,</span><span class="n">action</span><span class="o">=</span><span class="s1">'store_true'</span><span class="p">,</span>\
<span class="n">help</span><span class="o">=</span><span class="s1">'Suppress warnings about missing files [default: </span><span class="si">%d</span><span class="s1">efault]'</span><span class="p">,</span>
<span class="n">default</span><span class="o">=</span><span class="kc">False</span><span class="p">)</span>
<span class="p">]</span>
<span class="n">script_info</span><span class="p">[</span><span class="s1">'version'</span><span class="p">]</span> <span class="o">=</span> <span class="n">__version__</span>
<span class="k">def</span> <span class="nf">main</span><span class="p">():</span>
<span class="n">option_parser</span><span class="p">,</span> <span class="n">opts</span><span class="p">,</span> <span class="n">args</span> <span class="o">=</span>\
<span class="n">parse_command_line_parameters</span><span class="p">(</span><span class="o">**</span><span class="n">script_info</span><span class="p">)</span>
<span class="n">suppress_errors</span> <span class="o">=</span> <span class="n">opts</span><span class="o">.</span><span class="n">suppress_errors</span>
<span class="n">input_fps</span> <span class="o">=</span> <span class="p">[]</span>
<span class="k">for</span> <span class="n">input_fp</span> <span class="ow">in</span> <span class="n">opts</span><span class="o">.</span><span class="n">input_fps</span><span class="o">.</span><span class="n">split</span><span class="p">(</span><span class="s1">','</span><span class="p">):</span>
<span class="n">input_fps</span><span class="o">.</span><span class="n">extend</span><span class="p">(</span><span class="n">glob</span><span class="p">(</span><span class="n">input_fp</span><span class="p">))</span>
<span class="k">for</span> <span class="n">input_fp</span> <span class="ow">in</span> <span class="n">input_fps</span><span class="p">:</span>
<span class="n">i</span> <span class="o">=</span> <span class="mi">0</span>
<span class="k">try</span><span class="p">:</span>
<span class="n">input_f</span> <span class="o">=</span> <span class="nb">open</span><span class="p">(</span><span class="n">input_fp</span><span class="p">,</span><span class="s1">'U'</span><span class="p">)</span>
<span class="k">except</span> <span class="ne">IOError</span><span class="p">,</span><span class="n">e</span><span class="p">:</span>
<span class="k">if</span> <span class="n">suppress_errors</span><span class="p">:</span>
<span class="k">continue</span>
<span class="k">else</span><span class="p">:</span>
<span class="nb">print</span> <span class="n">input_fp</span><span class="p">,</span> <span class="n">e</span>
<span class="k">for</span> <span class="n">s</span> <span class="ow">in</span> <span class="n">MinimalFastaParser</span><span class="p">(</span><span class="n">input_f</span><span class="p">):</span>
<span class="n">i</span> <span class="o">+=</span> <span class="mi">1</span>
<span class="nb">print</span> <span class="n">input_fp</span><span class="p">,</span> <span class="n">i</span>
<span class="k">if</span> <span class="n">__name__</span> <span class="o">==</span> <span class="s2">"__main__"</span><span class="p">:</span>
<span class="n">main</span><span class="p">()</span>
</pre></div>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="sidebar">
<div class="news">
<table id="feed"><tr><td><h3><a href="http://pycogent.wordpress.com/">PyCogent News and Announcements</a></h3></td>
</tr></table></div>
<h3>Table Of Contents</h3>
<ul class="current">
<li class="toctree-l1"><a class="reference internal" href="install.html">Quick installation using pip</a></li>
<li class="toctree-l1"><a class="reference internal" href="README.html">The Readme</a></li>
<li class="toctree-l1"><a class="reference internal" href="coding_guidelines.html">Coding guidelines</a></li>
<li class="toctree-l1"><a class="reference internal" href="data_file_links.html">The data files used in the documentation</a></li>
<li class="toctree-l1"><a class="reference internal" href="examples/index.html">Cogent Usage Examples</a></li>
<li class="toctree-l1"><a class="reference internal" href="cookbook/index.html">PyCogent Cookbook</a></li>
<li class="toctree-l1"><a class="reference internal" href="developer_notes.html">For Developers</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">Scripting guidelines</a></li>
<li class="toctree-l1"><a class="reference internal" href="licenses.html">Licenses and disclaimer</a></li>
<li class="toctree-l1"><a class="reference internal" href="ChangeLog.html">Changelog</a></li>
</ul>
<div role="search">
<h3 style="margin-top: 1.5em;">Search</h3>
<form class="search" action="search.html" method="get">
<input type="text" name="q" />
<input type="submit" value="Go" />
<input type="hidden" name="check_keywords" value="yes" />
<input type="hidden" name="area" value="default" />
</form>
</div>
</div>
<div class="clearer"></div>
</div>
</div>
<div class="footer-wrapper">
<div class="footer">
<div class="left">
<div role="navigation" aria-label="related navigaton">
<a href="developer_notes.html" title="For Developers"
>previous</a> |
<a href="licenses.html" title="Licenses and disclaimer"
>next</a> |
<a href="genindex.html" title="General Index"
>index</a>
</div>
<div role="note" aria-label="source link">
<br/>
<a href="_sources/scripting_guidelines.txt"
rel="nofollow">Show Source</a>
</div>
</div>
<div class="right">
<div class="footer" role="contentinfo">
© Copyright 2016, PyCogent Team.
Created using <a href="http://sphinx-doc.org/">Sphinx</a> 1.4.1.
</div>
</div>
<div class="clearer"></div>
</div>
</div>
</body>
</html>