Skip to content
Snippets Groups Projects
Commit d8c9c441 authored by Bienchen's avatar Bienchen
Browse files

Started introducing --json

parent a2a74135
No related branches found
No related tags found
No related merge requests found
......@@ -121,6 +121,14 @@ def _AssembleTrgTplAln(target, template):
new_aln.SetSequenceOffset(1, start)
return new_aln
class PM3StoreOnceAction(argparse.Action):
"""Action for argument parsing to prevent multiple calls to an option.
"""
def __call__(self, parser, namespace, values, option_string=None):
if getattr(namespace, self.dest, None) is not None:
raise argparse.ArgumentError(self, 'may only be used once.')
setattr(namespace, self.dest, values)
class PM3ArgumentParser(argparse.ArgumentParser):
"""
This class is a child of :class:`argparse.ArgumentParser`. It provides a
......@@ -224,12 +232,18 @@ class PM3ArgumentParser(argparse.ArgumentParser):
Options/ arguments added:
* ``--fasta trg:<NAME> <FILE>`` - describing a target-template alignment
with ``trg:`` marking the target sequence inside :file:`<FILE>`
* ``-f/ --fasta trg:<NAME> <FILE>`` - describing a target-template
alignment with ``trg:`` marking the target sequence inside
:file:`<FILE>`. The order of arguments is arbitrary which means file
names starting with :file:`trg:` will not work.
* ``-j/ --json <OBJECT>|<FILE>`` - target-template alignments in JSON
format. Either an object string or a file name. The string variant is
limited to how many characters your command line can gobble.
Exit codes related to alignment input:
* 11 - no prefix ``trg:`` found for an argument to '--fasta'
* 11 - no prefix ``trg:`` found for an argument to ``--fasta``
* 12 - a given alignment file does not exist
......@@ -248,9 +262,12 @@ class PM3ArgumentParser(argparse.ArgumentParser):
Attributes added to the namespace returned by
:meth:`Parse`:
* :attr:`fasta` - filled with the input of the '--fasta' argument, a
* :attr:`fasta` - filled with the input of the ``--fasta`` option, a
:class:`list` with multiple :class:`list` objects
* :attr:`json` - argument of the ``--json`` option, :class:`str`. May
be a filename of a JSON object string.
* :attr:`alignments` - :class:`ost.AlignmentList`, same order as
:attr:`fasta`
......@@ -264,17 +281,26 @@ class PM3ArgumentParser(argparse.ArgumentParser):
"""
Actually add alignment arguments/ options
"""
aln_grp = self.add_mutually_exclusive_group()
# FastA input: - always pairwise alignments
# - callable multiple times
# - goes by 'trg:<SEQNAME> <FILE>'
# - excludes JSON file/ object
# - leading whitespaces will be deleted
self.add_argument('-f', '--fasta', nargs=2, action='append',
metavar=('trg:<NAME>', '<FILE>'),
help='Pairwise alignment in FastA format, needs to '+
'declare what is the target sequence.')
# input: FastA/ JSON
# determined by extension: if we are wrong, the whole loading fails
# - leading whitespaces of FastA headers will be deleted
aln_grp.add_argument('-f', '--fasta', nargs=2, action='append',
metavar=('trg:<NAME>', '<FILE>'),
help='Pairwise alignment in FastA format, needs '+
'to declare what is the target sequence.')
# JSON input: - right as string or file
# - object starts with {, so not allowed for files
# - callable only ONCE: should include everything needed
# - fields/ objects used: ...
# - goes by '--json <OBJECT>|<FILE>'
# - excludes '--fasta'
# - leading whitespaces of sequence names will be deleted
aln_grp.add_argument('-j', '--json', metavar='<OBJECT>|<FILE>',
help='Alignments provided as JSON file/ object.',
action=PM3StoreOnceAction)
# possibility to add JSON: mention limitation!
class PM3OptionsNamespace(object):
......
......@@ -87,8 +87,9 @@ class PM3ArgParseTests(unittest.TestCase):
self.assertEqual(ecd.exception.code, 2)
self.assertEqual(self.log.messages['ERROR'],
['usage: test_pm3argparse.py [-h] [-f trg:<NAME> '+
'<FILE>]', 'test_pm3argparse.py: error: argument '+
'-f/--fasta: expected 2 argument(s)'])
'<FILE> | -j <OBJECT>|<FILE>]',
'test_pm3argparse.py: error: argument -f/--fasta: '+
'expected 2 argument(s)'])
def testAddAlignmentNoFileArg(self):
# check failure on missing file argument
......@@ -100,8 +101,9 @@ class PM3ArgParseTests(unittest.TestCase):
self.assertEqual(ecd.exception.code, 2)
self.assertEqual(self.log.messages['ERROR'],
['usage: test_pm3argparse.py [-h] [-f trg:<NAME> '+
'<FILE>]', 'test_pm3argparse.py: error: argument '+
'-f/--fasta: expected 2 argument(s)'])
'<FILE> | -j <OBJECT>|<FILE>]',
'test_pm3argparse.py: error: argument -f/--fasta: '+
'expected 2 argument(s)'])
def testAddAlignemntNoTrgPfx(self):
# checking that we fail on missing 'trg:' prefix for arguments of
......@@ -272,6 +274,38 @@ class PM3ArgParseTests(unittest.TestCase):
self.assertEqual(opts.alignments[0].GetSequence(1).name, '1AKE.B')
self.assertEqual(opts.aln_sources[0], 'data/fasta/1ake.fas')
def testAddAlignmentFastaAndJson(self):
# testing that --fasta and --json DO NOT work together
parser = pm3argparse.PM3ArgumentParser(__doc__, action=False)
parser.AddAlignment()
parser.AssembleParser()
with self.assertRaises(SystemExit) as ecd:
opts = parser.Parse(['--fasta', 'trg:target',
'data/fasta/1ake.fas', '--json', 'foo'])
self.assertEqual(ecd.exception.code, 2)
self.assertEqual(self.log.messages['ERROR'][0],
'usage: test_pm3argparse.py [-h] [-f trg:<NAME> '+
'<FILE> | -j <OBJECT>|<FILE>]',
'test_pm3argparse.py: error: argument -j/--json: '+
'not allowed with argument -f/--fasta')
def testAddAlignmentJsonMulti(self):
# passing --json multiple times is not allowed
# also serves as a unit test for PM3StoreOnceAction
parser = pm3argparse.PM3ArgumentParser(__doc__, action=False)
parser.AddAlignment()
parser.AssembleParser()
with self.assertRaises(SystemExit) as ecd:
opts = parser.Parse(['--json', 'foo', '--json', 'bar'])
self.assertEqual(ecd.exception.code, 2)
self.assertEqual(self.log.messages['ERROR'][0],
'usage: test_pm3argparse.py [-h] [-f trg:<NAME> '+
'<FILE> | -j <OBJECT>|<FILE>]',
'test_pm3argparse.py: error: argument -j/--json: '+
'may only be used once.')
# test no multiple --json
if __name__ == "__main__":
from ost import testutils
testutils.RunTests()
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment