ensembl-hive  2.7.0
ConfParser.pm
Go to the documentation of this file.
1 =head1 LICENSE
2 
3 See the NOTICE file distributed with this work for additional information
4 regarding copyright ownership.
5 
6 Licensed under the Apache License, Version 2.0 (the "License");
7 you may not use this file except in compliance with the License.
8 You may obtain a copy of the License at
9 
10  http://www.apache.org/licenses/LICENSE-2.0
11 
12 Unless required by applicable law or agreed to in writing, software
13 distributed under the License is distributed on an "AS IS" BASIS,
14 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 See the License for the specific language governing permissions and
16 limitations under the License.
17 
18 =cut
19 
20 
21 =head1 CONTACT
22 
23  Please email comments or questions to the public Ensembl
24  developers list at <http://lists.ensembl.org/mailman/listinfo/dev>.
25 
26  Questions may also be sent to the Ensembl help desk at
27  <http://www.ensembl.org/Help/Contact>.
28 
29 =cut
30 
31 =head1 NAME
32 
33 Bio::EnsEMBL::Utils::ConfParser - configuration parser for perl scripts
34 
35 =head1 SYNOPSIS
36 
37  my $conf = new Bio::EnsEMBL::Utils::ConfParser(
38  -SERVERROOT => "/path/to/ensembl",
39  -DEFAULT_CONF => "my.default.conf"
40  );
41 
42  # parse options from configuration file and commandline
43  $conf->parse_options(
44  'mandatory_string_opt=s' => 1,
45  'optional_numeric_opt=n' => 0,
46  );
47 
48  # get a paramter value
49  my $val = $conf->param('manadatory_string_op');
50 
51 =head1 DESCRIPTION
52 
53 This module parses a configuration file and the commandline options
54 passed to a script (the latter superseed the former). Configuration
55 files contain ini-file style name-value pairs, and the commandline
56 options are passed to Getopt::Long for parsing.
57 
58 The parameter values are consequently accessible via the param()
59 method. You can also create a commandline string of all current
60 parameters and their values to pass to another script.
61 
62 =cut
63 
64 package Bio::EnsEMBL::Utils::ConfParser;
65 
66 use strict;
67 use warnings;
68 no warnings 'uninitialized';
69 
70 use Getopt::Long;
71 use Text::Wrap;
72 use Cwd qw(abs_path);
73 use Pod::Usage qw(pod2usage);
74 use Bio::EnsEMBL::Utils::Argument qw(rearrange);
75 use Bio::EnsEMBL::Utils::Exception qw(throw warning);
76 use Bio::EnsEMBL::Utils::ScriptUtils qw(user_proceed);
77 
78 
79 =head2 new
80 
81  Arg [SERVERROOT] :
82  String $serverroot - root directory of your ensembl code
83  Arg [DEFAULT_CONF] :
84  String $default_conf - default configuration file
85  Example : my $conf = new Bio::EnsEMBL::Utils::ConfParser(
86  -SERVERROOT => '/path/to/ensembl',
87  -DEFAULT_CONF => 'my.default.conf'
88  );
89  Description : object constructor
90  Return type : Bio::EnsEMBL::Utils::ConfParser object
91  Exceptions : thrown if no serverroot is provided
92  Caller : general
93  Status : At Risk
94  : under development
95 
96 =cut
97 
98 sub new {
99  my $caller = shift;
100  my $class = ref($caller) || $caller;
101 
102  my ($serverroot, $default_conf) =
103  rearrange([qw(SERVERROOT DEFAULT_CONF)], @_);
104 
105  throw("You must supply a serverroot.") unless ($serverroot);
106 
107  my $self = {};
108  bless ($self, $class);
109 
110  $self->serverroot($serverroot);
111  $self->default_conf($default_conf || "$ENV{HOME}/.ensembl_script.conf");
112 
113  return $self;
114 }
115 
116 
117 =head2 parse_options
118 
119  Arg[1..n] : pairs of option definitions and mandatory flag (see below for
120  details)
121  Example : $conf->parse_options(
122  'mandatory_string_opt=s' => 1,
123  'optional_numeric_opt=n' => 0,
124  );
125  Description : This method reads options from an (optional) configuration file
126  and parses the commandline options supplied by the user.
127  Commandline options will superseed config file settings. The
128  string "$SERVERROOT" in the configuration entries will be
129  replaced by the appropriate value.
130 
131  The arguments passed to this method are pairs of a Getopt::Long
132  style option definition (in fact it will be passed to
133  GetOptions() directly) and a flag indicating whether this
134  option is mandatory (1) or optional (0).
135 
136  In addition to these user-defined options, a set of common
137  options is always parsed. See _common_options() for details.
138 
139  If you run your script with --interactive the user will be
140  asked to confirm the parameters after parsing.
141 
142  All parameters will then be accessible via $self->param('name').
143  Return type : true on success
144  Exceptions : thrown if configuration file can't be opened
145  thrown on missing mandatory parameters
146  Caller : general
147  Status : At Risk
148  : under development
149 
150 =cut
151 
152 sub parse_options {
153  my ($self, @params) = @_;
154 
155  # add common options to user supplied list
156  push @params, $self->_common_options;
157 
158  # read common commandline options
159  my %h;
160  my %params = @params;
161 
162  Getopt::Long::Configure('pass_through');
163  &GetOptions(\%h, keys %params);
164 
165  # reads config file
166  my $conffile = $h{'conffile'} || $self->default_conf;
167  $conffile = abs_path($conffile);
168 
169  if (-e $conffile) {
170  open(my $fh, '<', $conffile) or throw(
171  "Unable to open configuration file $conffile for reading: $!");
172 
173  my $serverroot = $self->serverroot;
174  my $last;
175 
176  while (my $line = <$fh>) {
177  chomp $line;
178 
179  # remove leading and trailing whitespace
180  $line =~ s/^\s*//;
181  $line =~ s/\s*$//;
182 
183  # join with next line if terminated with backslash (this is to allow
184  # multiline configuration settings
185  $line = $last . $line;
186  if ($line =~ /\\$/) {
187  $line =~ s/\\$//;
188  $last = $line;
189  next;
190  } else {
191  $last = undef;
192  }
193 
194  # remove comments
195  $line =~ s/^[#;].*//;
196  $line =~ s/\s+[;].*$//;
197 
198  # read options into internal parameter datastructure
199  next unless ($line =~ /(\w\S*)\s*=\s*(.*)/);
200  my $name = $1;
201  my $val = $2;
202 
203  # strip optional quotes from parameter values
204  $val =~ s/^["'](.*)["']/$1/;
205 
206  # replace $SERVERROOT with value
207  if ($val =~ /\$SERVERROOT/) {
208  $val =~ s/\$SERVERROOT/$serverroot/g;
209  $val = abs_path($val);
210  }
211  $self->param($name, $val);
212  }
213  close($fh);
214 
215  $self->param('conffile', $conffile);
216  }
217 
218  # override configured parameter with commandline options
219  map { $self->param($_, $h{$_}) } keys %h;
220 
221  # check for required params, convert comma to list, maintain an ordered
222  # list of parameters and list of 'flag' type params
223  my @missing = ();
224  my $i = 0;
225 
226  foreach my $param (@params) {
227  next if ($i++ % 2);
228 
229  my $required = $params{$param};
230  my ($list, $flag);
231  $list = 1 if ($param =~ /\@$/);
232  $flag = 1 if ($param =~ /!$/);
233  $param =~ s/(^\w+).*/$1/;
234 
235  $self->comma_to_list($param) if ($list);
236 
237  push @missing, $param if ($required and !$self->param($param));
238  push @{ $self->{'_ordered_params'} }, $param;
239  $self->{'_flag_params'}->{$param} = 1 if ($flag);
240  }
241 
242  if (@missing) {
243  throw("Missing parameters: @missing.\nYou must specify them on the commandline or in your conffile.\n");
244  }
245 
246  # error handling and --help
247  pod2usage(1) if ($self->param('help'));
248 
249  # ask user to confirm parameters to proceed
250  $self->confirm_params;
251 
252  return(1);
253 }
254 
255 
256 #
257 # Commonly used options. These are parsed by default even if they are not
258 # passed to parse_options() explicitely.
259 #
260 sub _common_options {
261  my $self = shift;
262  return (
263  'conffile|conf=s' => 0,
264  'logfile|log=s' => 0,
265  'logauto!' => 0,
266  'logautobase=s' => 0,
267  'logautoid=s' => 0,
268  'logpath=s' => 0,
269  'logappend|log_append|log-append!' => 0,
270  'loglevel=s' => 0,
271  'is_component|is-component!' => 0,
272  'interactive|i!' => 0,
273  'dry_run|dry-run|dry|n!' => 0,
274  'help|h|?' => 0,
275  );
276 }
277 
278 
279 =head2 confirm_params
280 
281  Example : $conf->confirm_params;
282  Description : If the script is run with the --interactive switch, this method
283  prints a table of all parameters and their values and asks user
284  to confirm if he wants to proceed.
285  Return type : true on success
286  Exceptions : none
287  Caller : parse_options()
288  Status : At Risk
289  : under development
290 
291 =cut
292 
293 sub confirm_params {
294  my $self = shift;
295 
296  if ($self->param('interactive')) {
297  # print parameter table
298  print "Running script with these parameters:\n\n";
299  print $self->list_param_values;
300 
301  # ask user if he wants to proceed
302  exit unless user_proceed("Continue?", 1, 'n');
303  }
304 
305  return(1);
306 }
307 
308 
309 =head2 param
310 
311  Arg[1] : Parameter name
312  Arg[2..n] : (optional) List of values to set
313  Example : # getter
314  my $dbname = $conf->param('dbname');
315 
316  # setter
317  $conf->param('port', 3306);
318  $conf->param('chromosomes', 1, 6, 'X');
319  Description : Getter/setter for parameters. Accepts single-value params and
320  list params.
321  Return type : Scalar value for single-value parameters, array of values for
322  list parameters
323  Exceptions : thrown if no parameter name is supplied
324  Caller : general
325  Status : At Risk
326  : under development
327 
328 =cut
329 
330 sub param {
331  my $self = shift;
332  my $name = shift or throw("You must supply a parameter name");
333 
334  # setter
335  if (@_) {
336  if (scalar(@_) == 1) {
337  # single value
338  $self->{'_param'}->{$name} = shift;
339  } else {
340  # list of values
341  undef $self->{'_param'}->{$name};
342  @{ $self->{'_param'}->{$name} } = @_;
343  }
344  }
345 
346  # getter
347  if (ref($self->{'_param'}->{$name}) eq 'ARRAY') {
348  # list parameter
349  return @{ $self->{'_param'}->{$name} };
350  } elsif (defined($self->{'_param'}->{$name})) {
351  # single-value parameter
352  return $self->{'_param'}->{$name};
353  } else {
354  return undef;
355  }
356 }
357 
358 
359 =head2 is_true
360 
361  Arg[1] : Parameter name
362  Example : unless ($conf->is_true('upload')) {
363  print "Won't upload data.\n";
364  next;
365  }
366  Description : Checks whether a param value is set to 'true', which is defined
367  here as TRUE (in the Perl sense) but not the string 'no'.
368  Return type : Boolean
369  Exceptions : thrown if no parameter name is supplied
370  Caller : general
371  Status : At Risk
372  : under development
373 
374 =cut
375 
376 sub is_true {
377  my $self = shift;
378  my $name = shift or throw("You must supply a parameter name");
379 
380  my $param = $self->param($name);
381 
382  if ($param and !($param =~ /^no$/i)) {
383  return(1);
384  } else {
385  return(0);
386  }
387 }
388 
389 
390 =head2 list_params
391 
392  Example : print "Current parameter names:\n";
393  foreach my $param (@{ $conf->list_params }) {
394  print " $param\n";
395  }
396  Description : Returns a list of the currently available parameter names. The
397  list will be in the same order as option definitions were
398  passed to the new() method.
399  Return type : Arrayref of parameter names
400  Exceptions : none
401  Caller : list_param_values(), create_commandline_options()
402  Status : At Risk
403  : under development
404 
405 =cut
406 
407 sub list_params {
408  my $self = shift;
409  return $self->{'_ordered_params'} || [];
410 }
411 
412 
413 =head2 list_param_values
414 
415  Example : print LOG $conf->list_param_values;
416  Description : prints a table of the parameters used in the script
417  Return type : String - the table to print
418  Exceptions : none
419  Caller : general
420  Status : At Risk
421  : under development
422 
423 =cut
424 
425 sub list_param_values {
426  my $self = shift;
427 
428  $Text::Wrap::colums = 72;
429 
430  my $txt = sprintf " %-20s%-40s\n", qw(PARAMETER VALUE);
431  $txt .= " " . "-"x70 . "\n";
432 
433  foreach my $key (@{ $self->list_params }) {
434  my $val;
435  if (defined($self->param($key))) {
436  $txt .= Text::Wrap::wrap(sprintf(' %-19s ', $key), ' 'x24,
437  join(", ", $self->param($key)))."\n";
438  }
439  }
440 
441  $txt .= "\n";
442 
443  return $txt;
444 }
445 
446 
447 =head2 create_commandline_options
448 
449  Arg[1..n] : param/value pairs which should be added to or override the
450  currently defined parameters
451  Example : $conf->create_commandline_options(
452  'dbname' => 'homo_sapiens_vega_33_35e',
453  'interactive' => 0
454  );
455  Description : Creates a commandline options string of all current paramters
456  that can be passed to another script.
457  Return type : String - commandline options string
458  Exceptions : none
459  Caller : general
460  Status : At Risk
461  : under development
462 
463 =cut
464 
465 sub create_commandline_options {
466  my ($self, %replace) = @_;
467 
468  my %param_hash;
469 
470  # deal with list values
471  foreach my $param (@{ $self->list_params }) {
472  my ($first, @rest) = $self->param($param);
473  next unless (defined($first));
474 
475  if (@rest) {
476  $first = join(",", $first, @rest);
477  }
478  $param_hash{$param} = $first;
479  }
480 
481  # replace values
482  foreach my $key (keys %replace) {
483  $param_hash{$key} = $replace{$key};
484  }
485 
486  # create the commandline options string
487  my $options_string;
488  foreach my $param (keys %param_hash) {
489 
490  my $val = $param_hash{$param};
491 
492  # deal with 'flag' type params correctly
493  if ($self->{'_flag_params'}->{$param}) {
494  # change 'myparam' to 'nomyparam' if no value set
495  $param = 'no'.$param unless ($val);
496 
497  # unset value (this is how flags behave)
498  $val = undef;
499  } else {
500  # don't add the param if it's not a flag param and no value is set
501  next unless (defined($val));
502 
503  # quote the value if it contains blanks
504  if ($val =~ /\s+/) {
505  # use an appropriate quoting style
506  ($val =~ /'/) ? ($val = qq("$val")) : ($val = qq('$val'));
507  }
508  }
509 
510  $options_string .= sprintf(qq(--%s %s ), $param, $val);
511  }
512 
513  return $options_string;
514 }
515 
516 
517 =head2 comma_to_list
518 
519  Arg[1..n] : list of parameter names to parse
520  Example : $conf->comma_to_list('chromosomes');
521  Description : Transparently converts comma-separated lists into arrays (to
522  allow different styles of commandline options, see perldoc
523  Getopt::Long for details). Parameters are converted in place
524  (accessible through $self->param('name')).
525  Return type : true on success
526  Exceptions : none
527  Caller : general
528  Status : At Risk
529  : under development
530 
531 =cut
532 
533 sub comma_to_list {
534  my $self = shift;
535 
536  foreach my $param (@_) {
537  $self->param($param, split (/,/, join (',', $self->param($param))));
538  }
539 
540  return(1);
541 }
542 
543 
544 =head2 list_or_file
545 
546  Arg[1] : Name of parameter to parse
547  Example : $conf->list_or_file('gene');
548  Description : Determines whether a parameter holds a list or it is a filename
549  to read the list entries from.
550  Return type : true on success
551  Exceptions : thrown if list file can't be opened
552  Caller : general
553  Status : At Risk
554  : under development
555 
556 =cut
557 
558 sub list_or_file {
559  my ($self, $param) = @_;
560 
561  my @vals = $self->param($param);
562  return unless (@vals);
563 
564  my $firstval = $vals[0];
565 
566  if (scalar(@vals) == 1 && -e $firstval) {
567  # we didn't get a list of values, but a file to read values from
568  @vals = ();
569 
570  open(my $fh, '<', $firstval) or throw("Cannot open $firstval for reading: $!");
571 
572  while(<$fh>){
573  chomp;
574  push(@vals, $_);
575  }
576 
577  close($fh);
578 
579  $self->param($param, @vals);
580  }
581 
582  $self->comma_to_list($param);
583 
584  return(1);
585 }
586 
587 
588 =head2 serverroot
589 
590  Arg[1] : (optional) String - root directory of your ensembl checkout
591  Example : my $serverroot = $conf->serverroot;
592  Description : Getter/setter for the root directory of your ensembl checkout.
593  Return type : String
594  Exceptions : none
595  Caller : new(), general
596  Status : At Risk
597  : under development
598 
599 =cut
600 
601 sub serverroot {
602  my $self = shift;
603  $self->{'_serverroot'} = shift if (@_);
604  return $self->{'_serverroot'};
605 }
606 
607 
608 =head2 default_conf
609 
610  Arg[1] : (optional) String - default configuration file
611  Example : $conf->default_conf('my.default.conf');
612  Description : Getter/setter for the default configuration file.
613  Return type : String
614  Exceptions : none
615  Caller : new(), general
616  Status : At Risk
617  : under development
618 
619 =cut
620 
621 sub default_conf {
622  my $self = shift;
623  $self->{'_default_conf'} = shift if (@_);
624  return $self->{'_default_conf'};
625 }
626 
627 
628 1;
629 
confirm
public confirm()
EnsEMBL
Definition: Filter.pm:1
Bio::EnsEMBL::Utils::ScriptUtils
Definition: ScriptUtils.pm:11
Bio::EnsEMBL::Utils::ConfParser
Definition: ConfParser.pm:41
run
public run()
Bio
Definition: AltAlleleGroup.pm:4
Bio::EnsEMBL::Utils::Argument
Definition: Argument.pm:34
Bio::EnsEMBL::Utils::Exception
Definition: Exception.pm:68