Command Line Interface

User guide

The command line interface has built in help. To display the help, please append -h to the program call, for example:

./patapy.py -h

The help option responds to arguments your provide, so you can get details about your method of choice with:

./patapy.py gsea -h

where gsea is the name of a method; likewise, you can display help for any of samples specification options (case/control/data), e.g.:

./patapy.py control -h

Predefined parsers

Parsers are defined in command_line.main module.

class CLI(parser_name=None, **kwargs)[source]

The main parser, the one exposed directly to the user.

parse_args(args)[source]

Same as parse_known_args() but all arguments must be parsed.

This is an equivalent of argparse.ArgumentParser.parse_args() although it does >not< support namespace keyword argument.

Comparing to parse_known_args(), this method handles help messages nicely (i.e. passes everything to argparse).

Parameters:args – strings to parse, default is sys.argv[1:]
produce(unknown_args)[source]

Post-process already parsed namespace.

You can override this method to create a custom objects in the parsed namespace (e.g. if you cannot specify the target class with Argument(type=X), because X depends on two or more arguments).

You can chery-pick the arguments which were not parsed by the current parser (e.g. when some step of parsing depends on provided arguments), but please remember to remove those from unknown_args list.

Remember to operate on the provided list object (do not rebind the name with unknown_args = [], as doing so will have no effect: use unknown_args.remove() instead).

class CLIExperiment(parser_name=None, **kwargs)[source]

Use both: case and control or data to create an Experiment.

produce(unknown_args=None)[source]

Post-process already parsed namespace.

You can override this method to create a custom objects in the parsed namespace (e.g. if you cannot specify the target class with Argument(type=X), because X depends on two or more arguments).

You can chery-pick the arguments which were not parsed by the current parser (e.g. when some step of parsing depends on provided arguments), but please remember to remove those from unknown_args list.

Remember to operate on the provided list object (do not rebind the name with unknown_args = [], as doing so will have no effect: use unknown_args.remove() instead).

class PhenotypeFactory(parser_name=None, **kwargs)[source]

Provide {parser_name} samples. Requires a file (or files) with samples.

The files should come in Delimiter Separated Values format (like .csv or .tsv). The default delimiter is a tab character. The first column of each file should contain gene identifiers.

To use only a subset of samples from files(s) specify column numbers (–columns) or sample names (–samples) of desired samples.

produce(unknown_args=None)[source]

Post-process already parsed namespace.

You can override this method to create a custom objects in the parsed namespace (e.g. if you cannot specify the target class with Argument(type=X), because X depends on two or more arguments).

You can chery-pick the arguments which were not parsed by the current parser (e.g. when some step of parsing depends on provided arguments), but please remember to remove those from unknown_args list.

Remember to operate on the provided list object (do not rebind the name with unknown_args = [], as doing so will have no effect: use unknown_args.remove() instead).

class SingleFileExperimentFactory(parser_name=None, **kwargs)[source]

Provide both: case and control samples from a single file.

This is just a shortcut for specifying the same file for both: case and control samples sets. You have to provide –case or –control (or both) to specify which columns contain controls.

If you specify only one of –case and –control, it will be assumed that all other columns should be used for the other set of samples (if you use –case 0,1,2 and your file has five columns with samples, then columns three and four will be used to create control samples).

To enable more advanced features, please use control`&`case options (instead of the currently selected data sub-parser).

produce(unknown_args=None)[source]

Post-process already parsed namespace.

You can override this method to create a custom objects in the parsed namespace (e.g. if you cannot specify the target class with Argument(type=X), because X depends on two or more arguments).

You can chery-pick the arguments which were not parsed by the current parser (e.g. when some step of parsing depends on provided arguments), but please remember to remove those from unknown_args list.

Remember to operate on the provided list object (do not rebind the name with unknown_args = [], as doing so will have no effect: use unknown_args.remove() instead).

Creating custom arguments and parsers

Please use command_line.parser module to create custom parsers and arguments.

class Argument(name=None, short=None, optional=True, as_many_as=None, **kwargs)[source]

Defines argument for Parser.

In essence, this is a wrapper for argparse.ArgumentParser.add_argument(), so most options (type, help) which work in standard Python parser will work with Argument too. Additionally, some nice features, like automated naming are available.

Worth to mention that when used with MethodParser, type and help will be automatically deduced.

class Parser(parser_name=None, **kwargs)[source]

Parser is a wrapper around Python built-in argparse.ArgumentParser.

Subclass the Parser to create your own parser.

Use help, description and epilog properties to adjust the help screen. By default help and description will be auto-generated using docstring and defined arguments.

Attach custom arguments and sub-parsers by defining class-variables with Argument and Parser instances.

Example:

class TheParser(Parser):
    help = 'This takes only one argument, but it is required'

    arg = Argument(optional=False, help='This is required')

class MyParser(Parser):
    description = 'This should be a longer text'

    my_argument = Argument(type=int, help='some number')
    my_sub_parser = TheParser()

    epilog = 'You can create a footer with this'

# To execute the parser use:

parser = MyParser()

# The commands will usually be `sys.argv[1:]`
commands = '--my_argument 4 my_sub_parser value'.split()

namespace = parser.parse_args(commands)

# `namespace` is a normal `argparse.Namespace`
assert namespace.my_argument == 4
assert namespace.my_sub_parser.arg == 'value'

Implementation details:

To enable behaviour not possible with limited, plain ArgumentParser (e.g. to dynamically attach a sub-parser, or to chain two or more sub-parsers together) the stored actions and sub-parsers are:

  • not attached permanently to the parser,
  • attached in a tricky way to enable desired behaviour,
  • executed directly or in hierarchical order.

Class-variables with parsers will be deep-copied on initialization, so you do not have to worry about re-use of parsers.

attach_argument(argument, parser=None)[source]

Attach Argument instance to given (or own) argparse.parser.

attach_subparsers()[source]

Only in order to show a nice help, really.

There are some issues when using subparsers added with the built-in add_subparsers for parsing. Instead subparsers are handled in a custom implementation of parse_known_args (which really builds upon the built-in one, just tweaking some places).

bind_argument(argument, name=None)[source]

Bind argument to current instance of Parser.

bind_parser(parser, name)[source]

Bind deep-copy of Parser with this instance (as a sub-parser).

Parameters:
  • parser (Parser) – parser to be bound as a sub-parser (must be already initialized)
  • name – name of the new sub-parser

This method takes care of ‘translucent’ sub-parsers (i.e. parsers which expose their arguments and sub-parsers to namespace above), saving their members to appropriate dicts (lifted_args/parsers).

description

Longer description of the parser.

Description is shown when user narrows down the help to the parser with: ./run.py sub_parser_name -h.

epilog

Use this to append text after the help message

error(message)[source]

Raises SystemExit with status code 2 and shows usage message.

help

A short message, shown as summary on >parent< parser help screen.

Help will be displayed for sub-parsers only.

parse_args(args=None)[source]

Same as parse_known_args() but all arguments must be parsed.

This is an equivalent of argparse.ArgumentParser.parse_args() although it does >not< support namespace keyword argument.

Comparing to parse_known_args(), this method handles help messages nicely (i.e. passes everything to argparse).

Parameters:args (Optional[Sequence[str]]) – strings to parse, default is sys.argv[1:]
parse_known_args(args)[source]

Parse known arguments, like argparse.ArgumentParser.parse_known_args().

Additional features (when compared to argparse implementation) are:
  • ability to handle multiple sub-parsers
  • validation with self.validate (run after parsing)
  • additional post-processing with self.produce (after validation)
produce(unknown_args)[source]

Post-process already parsed namespace.

You can override this method to create a custom objects in the parsed namespace (e.g. if you cannot specify the target class with Argument(type=X), because X depends on two or more arguments).

You can chery-pick the arguments which were not parsed by the current parser (e.g. when some step of parsing depends on provided arguments), but please remember to remove those from unknown_args list.

Remember to operate on the provided list object (do not rebind the name with unknown_args = [], as doing so will have no effect: use unknown_args.remove() instead).

pull_to_namespace_above

Makes the parser “translucent” for the end user.

Though parsing methods (as well as validate & produce) are still evaluated, the user won’t be able to see this sub-parser in command-line interface.

This is intended to provide additional logic separation layer & to keep the parsers nicely organized and nested, without forcing the end user to type in prolonged names to localise an argument in a sub-parser of a sub-parser of some other parser.

validate(opts)[source]

Perform additional validation, using Argument.validate.

As validation is performed after parsing, all arguments should be already accessible in self.namespace. This enables testing if arguments depending one on another have proper values.

dedent_help(text)[source]

Dedent text by four spaces

group_arguments(args, group_names)[source]

Group arguments into given groups + None group for all others