Support aliasing of input files via --as and querying from stdin.
@@ -7,6 +7,7 @@ import os
import os.path
import tempfile
import io
+import argparse
from kgtk.exceptions import KGTKException
@@ -24,12 +25,36 @@ def parser():
EXPLAIN_MODES = ('plan', 'full', 'expert')
INDEX_MODES = ('auto', 'expert', 'quad', 'triple', 'node1+label', 'node1', 'label', 'node2', 'none')
+class InputOptionAction(argparse.Action):
+ """Special-purpose argparse action that associates an input-specific option
+ (such as an alias) to the most recently parsed input file. NOTE: the 'dest'
+ value will be used as the key for the specific option in 'input_file_options'.
+ """
+ def __call__(self, parser, namespace, values, option_string=None):
+ input_options = getattr(namespace, 'input_file_options', {}) or {}
+ inputs = KGTKArgumentParser.get_input_file_list(getattr(namespace, 'input_files', []))
+ if len(inputs) < 1:
+ raise KGTKException('out-of-place input option: %s' % option_string)
+ # normalize path objects to strings:
+ input_file = str(inputs[-1])
+ # handle boolean args (also requires nargs=0):
+ if self.type == bool:
+ values = True
+ # we use self.dest as the key for this particular option:
+ input_options.setdefault(input_file, {})[self.dest] = values
+ setattr(namespace, 'input_file_options', input_options)
+
def add_arguments_extended(parser: KGTKArgumentParser, parsed_shared_args):
parser.accept_shared_argument('_debug')
parser.accept_shared_argument('_expert')
- parser.add_input_file(options=["-i", "--input-files"], dest='input_files', allow_list=True, default_stdin=False, allow_stdin=False,
- who="one or more named input files to query (maybe compressed)")
+ parser.add_input_file(options=["-i", "--input-files"], dest='input_files', allow_list=True, default_stdin=False, allow_stdin=True,
+ who="One or more input files to query (maybe compressed).")
+ parser.add_argument('--as', metavar='NAME', default={}, action=InputOptionAction, dest='alias',
+ help="alias name to be used for preceding input")
+ # future extension:
+ #parser.add_argument('--in-memory', default=False, type=bool, nargs=0, action=InputOptionAction, dest='in_memory',
+ # help="load the preceding input into a temporary in-memory table only")
parser.add_argument('--query', default=None, action='store', dest='query',
help="complete Kypher query combining all clauses," +
" if supplied, all other specialized clause arguments will be ignored")
@@ -115,12 +140,10 @@ def run(input_files: KGTKFiles,
loglevel = 2
print('OPTIONS:', options)
- # inputs = options.get('inputs') or []
- inputs = KGTKArgumentParser.get_input_file_list(input_files)
+ # normalize path objects to strings:
+ inputs = [str(f) for f in KGTKArgumentParser.get_input_file_list(input_files)]
if len(inputs) == 0:
- raise KGTKException('At least one named input file needs to be supplied')
- if '-' in inputs:
- raise KGTKException('Cannot yet handle input from stdin')
+ raise KGTKException('At least one input needs to be supplied')
output = options.get('output')
if output == '-':
@@ -137,6 +160,7 @@ def run(input_files: KGTKFiles,
store = sqlstore.SqliteStore(graph_cache, create=not os.path.exists(graph_cache), loglevel=loglevel)
query = kyquery.KgtkQuery(inputs, store, loglevel=loglevel,
+ options=options.get('input_file_options'),
query=options.get('query'),
match=options.get('match'),
where=options.get('where'),
