Mercurial > ~dholland > hg > swallowtail > index.cgi
comparison shelltools/query-pr/query.py @ 52:c0be30249ffe
Fix the argument handling.
author | David A. Holland |
---|---|
date | Sat, 02 Apr 2022 21:13:01 -0400 (2022-04-03) |
parents | ef6d572c4e1e |
children | 40f64a96481f |
comparison
equal
deleted
inserted
replaced
51:ef6d572c4e1e | 52:c0be30249ffe |
---|---|
2 | 2 |
3 import sys | 3 import sys |
4 import argparse | 4 import argparse |
5 import psycopg2 | 5 import psycopg2 |
6 | 6 |
7 program_description = """ | |
8 Search for and retrieve problem reports. | |
9 """ | |
10 program_version = "@VERSION@" | 7 program_version = "@VERSION@" |
11 | 8 |
12 ############################################################ | 9 ############################################################ |
13 # settings | 10 # settings |
14 | 11 |
15 outfile = sys.stdout | 12 outfile = sys.stdout |
16 outmaterial = "headers" | 13 outmaterial = "headers" |
17 outformat = "text" | 14 outformat = "text" |
15 | |
16 ############################################################ | |
17 # simple dump widget | |
18 | |
19 class Dumper: | |
20 def __init__(self, f): | |
21 self.f = f | |
22 self.indentation = 0 | |
23 def indent(self): | |
24 self.indentation += 3 | |
25 def unindent(self): | |
26 self.indentation -= 3 | |
27 def write(self, msg): | |
28 self.f.write(" " * self.indentation + msg + "\n") | |
18 | 29 |
19 ############################################################ | 30 ############################################################ |
20 # database field access | 31 # database field access |
21 | 32 |
22 # | 33 # |
665 # XXX need an http output mode so we can send the mimetype! | 676 # XXX need an http output mode so we can send the mimetype! |
666 sys.stdout.write(body) | 677 sys.stdout.write(body) |
667 # end print_attachment | 678 # end print_attachment |
668 | 679 |
669 ############################################################ | 680 ############################################################ |
670 # AST for query | 681 # AST for input query |
671 | 682 |
672 class Invocation: | 683 class Invocation: |
684 Q_TERM = 1 | |
685 Q_SQL = 2 | |
673 class Query: | 686 class Query: |
674 Q_TERM = 1 # XXX unused so far | |
675 Q_SQL = 2 | |
676 Q_AND = 3 | |
677 Q_OR = 4 | |
678 Q_TSTRING = 5 | |
679 Q_QSTRING = 6 | |
680 | |
681 def __init__(self, type): | 687 def __init__(self, type): |
682 self.type = type | 688 self.type = type |
683 def doterm(term): | 689 def dump(self, d): |
684 self = Query(Q_TERM) | 690 if self.type == Invocation.Q_TERM: |
685 self.term = term | 691 d.write("query.term({})".format(self.term)) |
686 return self | 692 else: |
687 def dosql(s): | 693 d.write("query.sql({})".format(self.sql)) |
688 self = Query(Q_SQL) | 694 def mkterm(term): |
689 self.sql = s | 695 self = Invocation.Query(Invocation.Q_TERM) |
690 return self | 696 self.term = term |
691 def doand(qs): | 697 return self |
692 self = Query(Q_AND) | 698 def mksql(s): |
693 self.args = qs | 699 self = Invocation.Query(Invocation.Q_SQL) |
694 return self | 700 self.sql = s |
695 def door(qs): | 701 return self |
696 self = Query(Q_OR) | |
697 self.args = qs | |
698 return self | |
699 # query term string | |
700 def dotstring(q): | |
701 self = Query(Q_TSTRING) | |
702 self.string = q | |
703 return self | |
704 # whole query string | |
705 def doqstring(q): | |
706 self = Query(Q_QSTRING) | |
707 self.string = q | |
708 return self | |
709 # end class Query | |
710 | 702 |
711 class Order: | 703 class Order: |
712 def __init__(self, field, rev = False): | 704 def __init__(self, field, rev = False): |
713 self.field = field | 705 self.field = field |
714 self.rev = rev | 706 self.rev = rev |
715 def dooldest(ign): | 707 def dump(self, d): |
716 return Order("number") | 708 d.write("order({}, {})".format(self.field, self.rev)) |
717 def donewest(ign): | 709 def mkoldest(): |
718 return Order("number", True) | 710 return Invocation.Order("number") |
719 def dostaleness(ign): | 711 def mknewest(): |
720 return Order("modified_date", True) | 712 return Invocation.Order("number", True) |
721 def dofield(field): | 713 def mkstaleness(): |
722 return Order(field) | 714 return Invocation.Order("modified_date", True) |
723 def dorevfield(field): | 715 def mkfield(field): |
724 return Order(field, True) | 716 return Invocation.Order(field) |
725 # end class Order | 717 def mkrevfield(field): |
718 return Invocation.Order(field, True) | |
726 | 719 |
727 class Search: | 720 class Search: |
728 def __init__(self, qs, openonly, publiconly, os): | 721 def __init__(self, qs, openonly, publiconly, os): |
729 self.queries = qs | 722 self.queries = qs |
730 self.openonly = openonly | 723 self.openonly = openonly |
731 self.publiconly = publiconly | 724 self.publiconly = publiconly |
732 self.orders = os | 725 self.orders = os |
733 # end class Search | 726 def dump(self, d): |
734 | 727 d.write("search({}, {})".format( |
728 "open" if self.openonly else "closed", | |
729 "public" if self.publiconly else "privileged")) | |
730 d.indent() | |
731 d.write("queries") | |
732 d.indent() | |
733 for query in self.queries: | |
734 query.dump(d) | |
735 d.unindent() | |
736 d.write("orders") | |
737 d.indent() | |
738 for order in self.orders: | |
739 order.dump(d) | |
740 d.unindent() | |
741 d.unindent() | |
742 | |
743 S_PR = 1 | |
744 S_MESSAGE = 2 | |
745 S_ATTACHMENT = 3 | |
735 class Selection: | 746 class Selection: |
736 S_PR = 1 | |
737 S_MESSAGE = 2 | |
738 S_ATTACHMENT = 3 | |
739 | |
740 def __init__(self, type): | 747 def __init__(self, type): |
741 self.type = type | 748 self.type = type |
742 def dopr(output, outformat): | 749 def dump(self, d): |
743 self = Selection(S_PR) | 750 if self.type == Invocation.S_PR: |
744 self.output = output | 751 d.write("selection.pr({}, {})".format( |
745 self.outformat = outformat | 752 self.output, self.outformat)) |
746 return self | 753 elif self.type == Invocation.S_MESSAGE: |
747 def domessage(arg): | 754 d.write("selection.message({})".format( |
748 self = Selection(S_MESSAGE) | 755 self.message)) |
749 self.message = arg | 756 else: |
750 return self | 757 d.write("selection.attachment({})".format( |
751 def doattachment(arg): | 758 self.attachment)) |
752 self = Selection(S_ATTACHMENT) | 759 def mkpr(output, outformat): |
753 self.attachment = arg | 760 self = Invocation.Selection(Invocation.S_PR) |
754 return self | 761 self.output = output |
755 # end class Selection | 762 self.outformat = outformat |
756 | 763 return self |
764 def mkmessage(arg): | |
765 self = Invocation.Selection(Invocation.S_MESSAGE) | |
766 self.message = arg | |
767 return self | |
768 def mkattachment(arg): | |
769 self = Invocation.Selection(Invocation.S_ATTACHMENT) | |
770 self.attachment = arg | |
771 return self | |
772 | |
773 OP_FIELDS = 1 | |
774 OP_SHOW = 2 | |
775 OP_RANGE = 3 | |
776 OP_SEARCH = 4 | |
757 class Op: | 777 class Op: |
758 # operation codes | |
759 OP_FIELDS = 1 | |
760 OP_SHOW = 2 | |
761 OP_RANGE = 3 | |
762 OP_SEARCH = 4 | |
763 | |
764 def __init__(self, type): | 778 def __init__(self, type): |
765 self.type = type | 779 self.type = type |
766 | 780 def dump(self, d): |
767 def dofields(): | 781 if self.type == Invocation.OP_FIELDS: |
768 return Op(OP_FIELDS) | 782 d.write("op.fields") |
769 def doshow(field): | 783 elif self.type == Invocation.OP_SHOW: |
770 self = Op(OP_SHOW) | 784 d.write("op.show({})".format(self.field)) |
771 self.field = field | 785 elif self.type == Invocation.OP_RANGE: |
772 return self | 786 d.write("op.range({})".format(self.field)) |
773 def dorange(field): | 787 else: |
774 self = Op(OP_RANGE) | 788 d.write("op.search:") |
775 self.field = field | 789 d.indent() |
776 return self | 790 self.search.dump(d) |
777 def dosearch(s, sels): | 791 for sel in self.sels: |
778 self = Op(OP_SEARCH) | 792 sel.dump(d) |
779 self.search = s | 793 d.unindent() |
780 self.sels = sels | 794 def mkfields(): |
781 return self | 795 return Invocation.Op(Invocation.OP_FIELDS) |
782 # end class Op | 796 def mkshow(field): |
797 self = Invocation.Op(Invocation.OP_SHOW) | |
798 self.field = field | |
799 return self | |
800 def mkrange(field): | |
801 self = Invocation.Op(Invocation.OP_RANGE) | |
802 self.field = field | |
803 return self | |
804 def mksearch(s, sels): | |
805 self = Invocation.Op(Invocation.OP_SEARCH) | |
806 self.search = s | |
807 self.sels = sels | |
808 return self | |
783 | 809 |
784 def __init__(self, ops): | 810 def __init__(self, ops): |
785 self.ops = ops | 811 self.ops = ops |
812 def dump(self, d): | |
813 d.write("invocation: {} ops".format(len(self.ops))) | |
814 d.indent() | |
815 for op in self.ops: | |
816 op.dump(d) | |
817 d.unindent() | |
786 # end class Invocation | 818 # end class Invocation |
787 | 819 |
788 ############################################################ | 820 ############################################################ |
789 # run (eval the SQL and print the results) | 821 # run (eval the SQL and print the results) |
790 | 822 |
967 | 999 |
968 ############################################################ | 1000 ############################################################ |
969 # arg handling | 1001 # arg handling |
970 | 1002 |
971 # | 1003 # |
972 # I swear, all getopt interfaces suck. | 1004 # I swear, all getopt interfaces suck. You have to write your own to |
1005 # not go mad. | |
973 # | 1006 # |
974 # Provide an argparse action for constructing something out of the | 1007 |
975 # argument value and appending that somewhere, since it can't do this | 1008 # Usage. |
976 # on its own. | 1009 def usage(): |
977 # | 1010 sys.stderr.write(""" |
978 # The way you use this: | 1011 query-pr: search for and retrieve problem reports |
979 # p.add_argument("--foo", action = CtorAppend, dest = 'mylist', | 1012 usage: query-pr [options] [searchterms] Query the database. |
980 # const = ctor) | 1013 query-pr [options] --sql QUERY Execute QUERY as the search. |
981 # where ctor is a function taking the option arg(s) and producing | 1014 query-pr [options] -s QUERY Same as --sql. |
982 # a value to append to mylist. | 1015 query-pr --fields List database fields. |
983 # | 1016 query-pr --show FIELD Print info about database field. |
984 # This itself is mangy even for what it is -- it seems like we should | 1017 query-pr --range FIELD Print extant range for database field. |
985 # be able to pass action=CtorAppend(ctor), but since it has to be a | 1018 query-pr --help / -h Print this message. |
986 # class that doesn't work... unless you make a new class for every | 1019 query-pr --version / -v Print version and exit. |
987 # ctor you want to use, which seems completely insane. | 1020 options: |
988 # | 1021 --search-string STRING Forcibly treat STRING as a search term. |
989 class CtorAppend(argparse.Action): | 1022 --message NUM / -m NUM Print a message by its ID number. |
990 def __call__(self, parser, namespace, values, option_string=None): | 1023 --attachment NUM / -a NUM Print an attachment by its ID number. |
991 items = getattr(namespace, self.dest) | 1024 --paranoid Deny unsafe settings. |
992 item = self.const(values) | 1025 filter options: |
993 items.append(item) | 1026 --open Exclude closed PRs. (default) |
994 setattr(namespace, self.dest, items) | 1027 --closed Include closed PRs. |
995 | 1028 --public Exclude confidential PRs. |
996 def getargs(): | 1029 --privileged Include confidential PRs. (default) |
997 p = argparse.ArgumentParser(program_description) | 1030 sort options: |
998 | 1031 --oldest Sort with oldest PRs first. (default) |
999 # note: -h/--help is built in by default | 1032 --newest Sort with newest PRs first. |
1000 p.add_argument("-v", "--version", | 1033 --staleness Sort by last modification time. |
1001 action='version', version=program_version, | 1034 --orderby FIELD Sort by specific field. |
1002 help="Print program version and exit") | 1035 output options: |
1003 | 1036 --raw / -r Print raw SQL output. |
1004 p.add_argument("--show", nargs=1, | 1037 --list / -l Print in list form. |
1005 action=CtorAppend, dest='ops', | 1038 --headers Print headers only. |
1006 const=Invocation.Op.doshow, | 1039 --meta / --metadata Print all metadata. |
1007 help="Show description of field") | 1040 --full / -f Print entire PR. |
1008 p.add_argument("--range", nargs=1, | 1041 --text Print text. (default) |
1009 action=CtorAppend, dest='ops', | 1042 --csv Print CSV. |
1010 const=Invocation.Op.dorange, | 1043 --xml Print XML. |
1011 help="Show range of extant values for field") | 1044 --json Print JSON. |
1012 | 1045 --rdf Print RDF. |
1013 p.add_argument("--search", nargs=1, | 1046 --rdflike Print RDF-like text. |
1014 action=CtorAppend, dest='queries', | 1047 search terms: |
1015 const=Invocation.Query.doqstring, | 1048 NUM Single PR by number. |
1016 help="Force string to be read as a search string") | 1049 NUM-[NUM] Range of PRs by number. |
1017 p.add_argument("-s", "--sql", nargs=1, | 1050 TEXT Search string |
1018 action=CtorAppend, dest='queries', | 1051 FIELD:TEXT Search string for a particular field. |
1019 const=Invocation.Query.dosql, | 1052 FIELD: Use the field's default search string. |
1020 help="Supply explicit sql query as search") | 1053 derived fields: |
1021 | 1054 arrived-before:DATE Arrival date before DATE. |
1022 p.add_argument("--open", | 1055 arrived-after:DATE Arrival date after DATE. |
1023 action='store_const', dest='openonly', const="True", | 1056 closed-before:DATE Close date before DATE. |
1024 help="Exclude closed PRs (default)") | 1057 closed-after:DATE Close date after DATE, or none. |
1025 p.add_argument("--closed", | 1058 last-modified-before:DATE Last modified before DATE. |
1026 action='store_const', dest='openonly', const="False", | 1059 last-modified-after:DATE Last modified after DATE. |
1027 help="Include closed PRs in search") | 1060 stale:TIME Last modified at least TIME ago. |
1028 p.add_argument("--public", | 1061 Explicit SQL queries should return lists of PR numbers (only). |
1029 action='store_const', dest='publiconly', const="True", | 1062 """) |
1030 help="Exclude confidential PRs") | 1063 |
1031 p.add_argument("--privileged", | 1064 # Widget to hold argv and allow peeling args off one at a time. |
1032 action='store_const', dest='publiconly', const="False", | 1065 class ArgHolder: |
1033 help="Allow confidential PRs (default)") | 1066 def __init__(self, argv): |
1034 | 1067 self.argc = len(argv) |
1035 p.add_argument("--oldest", | 1068 self.argv = argv |
1036 action=CtorAppend, dest='orders', | 1069 self.pos = 1 |
1037 const=Invocation.Order.dooldest, | 1070 def next(self): |
1038 help="Sort output with oldest PRs first") | 1071 if self.pos >= self.argc: |
1039 p.add_argument("--newest", | 1072 return None |
1040 action=CtorAppend, dest='orders', | 1073 ret = self.argv[self.pos] |
1041 const=Invocation.Order.donewest, | 1074 self.pos += 1 |
1042 help="Sort output with newest PRs first") | 1075 return ret |
1043 p.add_argument("--staleness", | 1076 def getarg(self, opt): |
1044 action=CtorAppend, dest='orders', | 1077 ret = self.next() |
1045 const=Invocation.Order.dostaleness, | 1078 if ret is None: |
1046 help="Sort output by time since last modification") | 1079 msg = "Option {} requires an argument\n".format(opt) |
1047 p.add_argument("--orderby", nargs=1, | 1080 sys.stderr.write(msg) |
1048 action=CtorAppend, dest='orders', | 1081 exit(1) |
1049 const=Invocation.Order.dofield, | 1082 return ret |
1050 help="Sort output by specific field") | 1083 |
1051 p.add_argument("--revorderby", nargs=1, | 1084 # Read the argument list and convert it into an Invocation. |
1052 action=CtorAppend, dest='orders', | 1085 def getargs(argv): |
1053 const=Invocation.Order.dorevfield, | 1086 # Results |
1054 help="Sort output by specific field, reversed") | 1087 ops = [] |
1055 | 1088 orders = [] |
1056 p.add_argument("-m", "--message", nargs=1, | 1089 queries = [] |
1057 action=CtorAppend, dest='selections', | 1090 selections = [] |
1058 const=Invocation.Selection.domessage, | 1091 output = "LIST" |
1059 help="Print selected message (single PR only)") | 1092 outformat = "TEXT" |
1060 p.add_argument("-a", "--attachment", nargs=1, | 1093 openonly = True |
1061 action=CtorAppend, dest='selections', | 1094 publiconly = False |
1062 const=Invocation.Selection.doattachment, | 1095 paranoid = False |
1063 help="Print selected attachment (single PR only)") | 1096 nomoreoptions = False |
1064 | 1097 |
1065 p.add_argument("-r", "--raw", | 1098 # |
1066 action = 'store_const', const="RAW", | 1099 # Functions for the options |
1067 dest = 'output', | 1100 # |
1068 help="Print exactly what the database returns") | 1101 |
1069 p.add_argument("-l", "--list", | 1102 def do_paranoid(): |
1070 action = 'store_const', const="LIST", | 1103 nonlocal paranoid, publiconly |
1071 dest = 'output', | 1104 paranoid = True |
1072 help="Print in list form (default)") | 1105 publiconly = True |
1073 p.add_argument("--headers", | 1106 |
1074 action = 'store_const', const="HEADERS", | 1107 def do_help(): |
1075 dest = 'output', | 1108 usage() |
1076 help="Print header information only") | 1109 exit(0) |
1077 p.add_argument("--meta", | 1110 def do_version(): |
1078 action = 'store_const', const="META", | 1111 msg = "query-pr {}\n".format(program_version) |
1079 dest = 'output', | 1112 sys.stdout.write(msg) |
1080 help="Print all metadata") | 1113 exit(0) |
1081 p.add_argument("--metadata", | 1114 def do_fields(): |
1082 action = 'store_const', const="META", | 1115 ops.append(Invocation.mkfields()) |
1083 dest = 'output') | 1116 def do_show(field): |
1084 p.add_argument("-f", "--full", | 1117 ops.append(Invocation.mkshow(field)) |
1085 action = 'store_const', const="FULL", | 1118 def do_range(field): |
1086 dest = 'output', | 1119 ops.append(Invocation.mkrange(field)) |
1087 help="Print everything") | 1120 |
1088 | 1121 def do_search(term): |
1089 p.add_argument("--text", | 1122 queries.append(Invocation.mkterm(term)) |
1090 action = 'store_const', const="TEXT", | 1123 def do_sql(text): |
1091 dest = 'outformat', | 1124 assert(not paranoid) |
1092 help="Print in text format (default)") | 1125 queries.append(Invocation.mksql(text)) |
1093 p.add_argument("--csv", | 1126 |
1094 action = 'store_const', const="CSV", | 1127 def do_open(): |
1095 dest = 'outformat', | 1128 nonlocal openonly |
1096 help="Print a CSV file") | 1129 openonly = True |
1097 p.add_argument("--xml", | 1130 def do_closed(): |
1098 action = 'store_const', const="XML", | 1131 nonlocal openonly |
1099 dest = 'outformat', | 1132 openonly = False |
1100 help="Print in XML") | 1133 def do_public(): |
1101 p.add_argument("--json", | 1134 nonlocal publiconly |
1102 action = 'store_const', const="JSON", | 1135 publiconly = True |
1103 dest = 'outformat', | 1136 def do_privileged(): |
1104 help="Print in JSON") | 1137 nonlocal publiconly |
1105 p.add_argument("--rdf", | 1138 assert(not paranoid) |
1106 action = 'store_const', const="RDF", | 1139 publiconly = False |
1107 dest = 'outbformat', | 1140 |
1108 help="Print in RDF") | 1141 def do_oldest(): |
1109 p.add_argument("--rdflike", | 1142 orders.append(Invocation.mkoldest()) |
1110 action = 'store_const', const="RDFLIKE", | 1143 def do_newest(): |
1111 dest = 'outformat', | 1144 orders.append(Invocation.mknewest()) |
1112 help="Print RDF-like text") | 1145 def do_staleness(): |
1113 | 1146 orders.append(Invocation.mkstaleness()) |
1114 p.add_argument("TERM", nargs='*', | 1147 def do_orderby(field): |
1115 action=CtorAppend, dest='queries', | 1148 orders.append(Invocation.mkfield(field)) |
1116 const=Invocation.Query.doqstring, | 1149 def do_revorderby(field): |
1117 help="Search term") | 1150 orders.append(Invocation.mkrevfield(field)) |
1118 | 1151 |
1119 args = p.parse_args() | 1152 def do_message(n): |
1120 | 1153 selections.append(Invocation.mkmessage(n)) |
1121 ops = args.ops | 1154 def do_attachment(n): |
1122 if ops is None: | 1155 selections.append(Invocation.mkattachment(n)) |
1123 ops = [] | 1156 |
1124 queries = args.queries | 1157 def do_raw(): |
1125 if queries is not None: | 1158 nonlocal output |
1126 openonly = args.openonly | 1159 output = "RAW" |
1127 if openonly is None: | 1160 def do_list(): |
1128 openonly = True | 1161 nonlocal output |
1129 publiconly = args.publiconly | 1162 output = "LIST" |
1130 if publiconly is None: | 1163 def do_headers(): |
1131 publiconly = False | 1164 nonlocal output |
1132 orders = args.orders | 1165 output = "HEADERS" |
1133 if orders is None: | 1166 def do_meta(): |
1134 orders = [Invocation.Order.dooldest(None)] | 1167 nonlocal output |
1135 output = args.output | 1168 output = "META" |
1136 if output is None: | 1169 def do_full(): |
1137 output = "LIST" | 1170 nonlocal output |
1138 outformat = args.outformat | 1171 output = "FULL" |
1139 if outformat is None: | 1172 |
1140 outformat = "TEXT" | 1173 def do_text(): |
1141 selections = args.selections | 1174 nonlocal outformat |
1142 if selections is None: | 1175 outformat = "TEXT" |
1143 sel = Invocation.Selection.dopr(output, outformat) | 1176 def do_csv(): |
1144 selections = [sel] | 1177 nonlocal outformat |
1145 search = Search(queries, openonly, publiconly, orders) | 1178 outformat = "CSV" |
1146 op = dosearch(search, selections) | 1179 def do_xml(): |
1147 ops.append(op) | 1180 nonlocal outformat |
1148 # endif | 1181 outformat = "XML" |
1182 def do_json(): | |
1183 nonlocal outformat | |
1184 outformat = "JSON" | |
1185 def do_rdf(): | |
1186 nonlocal outformat | |
1187 outformat = "RDF" | |
1188 def do_rdflike(): | |
1189 nonlocal outformat | |
1190 outformat = "RDFLIKE" | |
1191 | |
1192 def do_unknown(opt): | |
1193 sys.stderr.write("Unknown option {}\n".format(opt)) | |
1194 exit(1) | |
1195 | |
1196 args = ArgHolder(argv) | |
1197 while True: | |
1198 arg = args.next() | |
1199 if arg is None: | |
1200 break | |
1201 | |
1202 if nomoreoptions or arg[0] != "-": | |
1203 do_search(arg) | |
1204 elif arg == "--": | |
1205 nomoreoptions = True | |
1206 # Long options | |
1207 elif arg == "--attachment": | |
1208 do_attachment(args.getarg(arg)) | |
1209 elif arg.startswith("--attachment="): | |
1210 do_message(arg[13:]) | |
1211 elif arg == "--closed": | |
1212 do_closed() | |
1213 elif arg == "--csv": | |
1214 do_csv() | |
1215 elif arg == "--fields": | |
1216 do_fields() | |
1217 elif arg == "--full": | |
1218 do_full() | |
1219 elif arg == "--headers": | |
1220 do_headers() | |
1221 elif arg == "--help": | |
1222 do_help() | |
1223 elif arg == "--json": | |
1224 do_json() | |
1225 elif arg == "--list": | |
1226 do_list() | |
1227 elif arg == "--message": | |
1228 do_message(args.getarg(arg)) | |
1229 elif arg.startswith("--message="): | |
1230 do_message(arg[10:]) | |
1231 elif arg == "--meta": | |
1232 do_meta() | |
1233 elif arg == "--metadata": | |
1234 do_meta() | |
1235 elif arg == "--newest": | |
1236 do_newest() | |
1237 elif arg == "--oldest": | |
1238 do_oldest() | |
1239 elif arg == "--orderby": | |
1240 do_orderby(args.getarg(arg)) | |
1241 elif arg.startswith("--orderby="): | |
1242 do_orderby(arg[10:]) | |
1243 elif arg == "--open": | |
1244 do_open() | |
1245 elif arg == "--paranoid": | |
1246 do_paranoid() | |
1247 elif arg == "--public": | |
1248 do_public() | |
1249 elif arg == "--privileged" and not paranoid: | |
1250 do_privileged() | |
1251 elif arg == "--range": | |
1252 do_range(args.getarg(arg)) | |
1253 elif arg.startswith("--range="): | |
1254 do_range(arg[8:]) | |
1255 elif arg == "--raw": | |
1256 do_raw() | |
1257 elif arg == "--rdf": | |
1258 do_rdf() | |
1259 elif arg == "--rdflike": | |
1260 do_rdflike() | |
1261 elif arg == "--revorderby": | |
1262 do_revorderby(args.getarg(arg)) | |
1263 elif arg.startswith("--revorderby="): | |
1264 do_revorderby(arg[13:]) | |
1265 elif arg == "--search": | |
1266 do_search(args.getarg(arg)) | |
1267 elif arg.startswith("--search="): | |
1268 do_search(arg[9:]) | |
1269 elif arg == "--show": | |
1270 do_show(args.getarg(arg)) | |
1271 elif arg.startswith("--show="): | |
1272 do_show(arg[7:]) | |
1273 elif arg == "--sql" and not paranoid: | |
1274 do_sql(args.getarg(arg)) | |
1275 elif arg.startswith("--sql=") and not paranoid: | |
1276 do_sql(arg[7:]) | |
1277 elif arg == "--staleness": | |
1278 do_staleness() | |
1279 elif arg == "--text": | |
1280 do_text() | |
1281 elif arg == "--version": | |
1282 do_version() | |
1283 elif arg == "--xml": | |
1284 do_xml() | |
1285 elif arg.startswith("--"): | |
1286 do_unknown(arg) | |
1287 else: | |
1288 # short options | |
1289 i = 1 | |
1290 n = len(arg) | |
1291 while i < n: | |
1292 opt = arg[i] | |
1293 i += 1 | |
1294 def getarg(): | |
1295 nonlocal i | |
1296 if i < n: | |
1297 ret = arg[i:] | |
1298 else: | |
1299 ret = args.getarg("-" + opt) | |
1300 i = n | |
1301 return ret | |
1302 | |
1303 if opt == "a": | |
1304 do_attachment(getarg()) | |
1305 elif opt == "f": | |
1306 do_full() | |
1307 elif opt == "h": | |
1308 do_help() | |
1309 elif opt == "l": | |
1310 do_list() | |
1311 elif opt == "m": | |
1312 do_message(getarg()) | |
1313 elif opt == "s" and not paranoid: | |
1314 do_sql(getarg()) | |
1315 elif opt == "r": | |
1316 do_raw() | |
1317 elif opt == "v": | |
1318 do_version() | |
1319 else: | |
1320 do_unknown("-" + opt) | |
1321 | |
1322 # Now convert what we got to a single thing. | |
1323 if queries != []: | |
1324 if orders == []: | |
1325 orders = [Invocation.mkoldest()] | |
1326 if selections == []: | |
1327 selections = [Invocation.mkpr(output, outformat)] | |
1328 search = Invocation.Search(queries, openonly, publiconly, orders) | |
1329 ops.append(Invocation.mksearch(search, selections)) | |
1330 else: | |
1331 if orders != []: | |
1332 msg = "No queries given for requested orderings\n" | |
1333 sys.stderr.write(msg) | |
1334 exit(1) | |
1335 if selections != []: | |
1336 msg = "No queries given for requested selections\n" | |
1337 sys.stderr.write(msg) | |
1338 exit(1) | |
1149 | 1339 |
1150 return Invocation(ops) | 1340 return Invocation(ops) |
1151 # end getargs | 1341 # end getargs |
1152 | 1342 |
1153 ############################################################ | 1343 ############################################################ |
1154 # main | 1344 # main |
1155 | 1345 |
1156 todo = getargs() | 1346 todo = getargs(sys.argv) |
1347 #todo.dump(Dumper(sys.stdout)) | |
1348 | |
1157 opendb() | 1349 opendb() |
1158 fetch_classifications() | 1350 fetch_classifications() |
1159 todo = compile(todo) | 1351 todo = compile(todo) |
1160 run(todo) | 1352 run(todo) |
1161 closedb() | 1353 closedb() |