|
1 | | -#!/usr/bin/env python |
2 | | -# -*- coding: UTF-8 -*- |
3 | | -"""Planet cache tool. |
| 1 | +#!/usr/bin/env python3 |
| 2 | +"""Planet cache tool.""" |
4 | 3 |
|
5 | | -""" |
6 | | - |
7 | | -__authors__ = [ "Scott James Remnant <scott@netsplit.com>", |
8 | | - "Jeff Waugh <jdub@perkypants.org>" ] |
| 4 | +__authors__ = [ |
| 5 | + "Scott James Remnant <scott@netsplit.com>", |
| 6 | + "Jeff Waugh <jdub@perkypants.org>", |
| 7 | +] |
9 | 8 | __license__ = "Python" |
10 | 9 |
|
11 | 10 |
|
| 11 | +import argparse |
| 12 | +import configparser |
12 | 13 | import os |
| 14 | +import shelve |
13 | 15 | import sys |
14 | 16 | import time |
15 | | -import dbhash |
16 | | -import ConfigParser |
17 | 17 |
|
18 | 18 | import planet |
19 | 19 |
|
20 | 20 |
|
21 | 21 | def usage(): |
22 | | - print "Usage: planet-cache [options] CACHEFILE [ITEMID]..." |
23 | | - print |
24 | | - print "Examine and modify information in the Planet cache." |
25 | | - print |
26 | | - print "Channel Commands:" |
27 | | - print " -C, --channel Display known information on the channel" |
28 | | - print " -L, --list List items in the channel" |
29 | | - print " -K, --keys List all keys found in channel items" |
30 | | - print |
31 | | - print "Item Commands (need ITEMID):" |
32 | | - print " -I, --item Display known information about the item(s)" |
33 | | - print " -H, --hide Mark the item(s) as hidden" |
34 | | - print " -U, --unhide Mark the item(s) as not hidden" |
35 | | - print |
36 | | - print "Other Options:" |
37 | | - print " -h, --help Display this help message and exit" |
| 22 | + print("Usage: planet-cache [options] CACHEFILE [ITEMID]...") |
| 23 | + print() |
| 24 | + print("Examine and modify information in the Planet cache.") |
| 25 | + print() |
| 26 | + print("Channel Commands:") |
| 27 | + print(" -C, --channel Display known information on the channel") |
| 28 | + print(" -L, --list List items in the channel") |
| 29 | + print(" -K, --keys List all keys found in channel items") |
| 30 | + print() |
| 31 | + print("Item Commands (need ITEMID):") |
| 32 | + print(" -I, --item Display known information about the item(s)") |
| 33 | + print(" -H, --hide Mark the item(s) as hidden") |
| 34 | + print(" -U, --unhide Mark the item(s) as not hidden") |
| 35 | + print() |
| 36 | + print("Other Options:") |
| 37 | + print(" -h, --help Display this help message and exit") |
38 | 38 | sys.exit(0) |
39 | 39 |
|
| 40 | + |
40 | 41 | def usage_error(msg, *args): |
41 | | - print >>sys.stderr, msg, " ".join(args) |
42 | | - print >>sys.stderr, "Perhaps you need --help ?" |
| 42 | + print(msg, " ".join(args), file=sys.stderr) |
| 43 | + print("Perhaps you need --help ?", file=sys.stderr) |
43 | 44 | sys.exit(1) |
44 | 45 |
|
| 46 | + |
45 | 47 | def print_keys(item, title): |
46 | 48 | keys = item.keys() |
47 | | - keys.sort() |
48 | | - key_len = max([ len(k) for k in keys ]) |
| 49 | + key_len = max([len(k) for k in sorted(keys)]) |
49 | 50 |
|
50 | | - print title + ":" |
51 | | - for key in keys: |
| 51 | + print(title + ":") |
| 52 | + for key in sorted(keys): |
52 | 53 | if item.key_type(key) == item.DATE: |
53 | 54 | value = time.strftime(planet.TIMEFMT_ISO, item[key]) |
54 | 55 | else: |
55 | 56 | value = str(item[key]) |
56 | | - print " %-*s %s" % (key_len, key, fit_str(value, 74 - key_len)) |
| 57 | + print(" %-*s %s" % (key_len, key, fit_str(value, 74 - key_len))) |
| 58 | + |
57 | 59 |
|
58 | 60 | def fit_str(string, length): |
59 | 61 | if len(string) <= length: |
60 | 62 | return string |
61 | 63 | else: |
62 | | - return string[:length-4] + " ..." |
| 64 | + return string[: length - 4] + " ..." |
63 | 65 |
|
64 | 66 |
|
65 | 67 | if __name__ == "__main__": |
66 | | - cache_file = None |
67 | | - want_ids = 0 |
68 | 68 | ids = [] |
69 | 69 |
|
70 | | - command = None |
71 | | - |
72 | | - for arg in sys.argv[1:]: |
73 | | - if arg == "-h" or arg == "--help": |
74 | | - usage() |
75 | | - elif arg == "-C" or arg == "--channel": |
76 | | - if command is not None: |
77 | | - usage_error("Only one command option may be supplied") |
78 | | - command = "channel" |
79 | | - elif arg == "-L" or arg == "--list": |
80 | | - if command is not None: |
81 | | - usage_error("Only one command option may be supplied") |
82 | | - command = "list" |
83 | | - elif arg == "-K" or arg == "--keys": |
84 | | - if command is not None: |
85 | | - usage_error("Only one command option may be supplied") |
86 | | - command = "keys" |
87 | | - elif arg == "-I" or arg == "--item": |
88 | | - if command is not None: |
89 | | - usage_error("Only one command option may be supplied") |
90 | | - command = "item" |
91 | | - want_ids = 1 |
92 | | - elif arg == "-H" or arg == "--hide": |
93 | | - if command is not None: |
94 | | - usage_error("Only one command option may be supplied") |
95 | | - command = "hide" |
96 | | - want_ids = 1 |
97 | | - elif arg == "-U" or arg == "--unhide": |
98 | | - if command is not None: |
99 | | - usage_error("Only one command option may be supplied") |
100 | | - command = "unhide" |
101 | | - want_ids = 1 |
102 | | - elif arg.startswith("-"): |
103 | | - usage_error("Unknown option:", arg) |
104 | | - else: |
105 | | - if cache_file is None: |
106 | | - cache_file = arg |
107 | | - elif want_ids: |
108 | | - ids.append(arg) |
109 | | - else: |
110 | | - usage_error("Unexpected extra argument:", arg) |
111 | | - |
112 | | - if cache_file is None: |
| 70 | + parser = argparse.ArgumentParser( |
| 71 | + description="Examine and modify information in the Planet cache." |
| 72 | + ) |
| 73 | + parser.add_argument( |
| 74 | + "-C", |
| 75 | + "--channel", |
| 76 | + action="store_const", |
| 77 | + const="channel", |
| 78 | + dest="command", |
| 79 | + help="Display known information on the channel", |
| 80 | + ) |
| 81 | + parser.add_argument( |
| 82 | + "-L", |
| 83 | + "--list", |
| 84 | + action="store_const", |
| 85 | + const="list", |
| 86 | + dest="command", |
| 87 | + help="List items in the channel", |
| 88 | + ) |
| 89 | + parser.add_argument( |
| 90 | + "-K", |
| 91 | + "--keys", |
| 92 | + action="store_const", |
| 93 | + const="keys", |
| 94 | + dest="command", |
| 95 | + help="List all keys found in channel items", |
| 96 | + ) |
| 97 | + parser.add_argument( |
| 98 | + "-I", |
| 99 | + "--item", |
| 100 | + action="store_const", |
| 101 | + const="item", |
| 102 | + dest="command", |
| 103 | + help="Display known information about the item(s)", |
| 104 | + ) |
| 105 | + parser.add_argument( |
| 106 | + "-H", |
| 107 | + "--hide", |
| 108 | + action="store_const", |
| 109 | + const="hide", |
| 110 | + dest="command", |
| 111 | + help="Mark the item(s) as hidden", |
| 112 | + ) |
| 113 | + parser.add_argument( |
| 114 | + "-U", |
| 115 | + "--unhide", |
| 116 | + action="store_const", |
| 117 | + const="unhide", |
| 118 | + dest="command", |
| 119 | + help="Mark the item(s) as not hidden", |
| 120 | + ) |
| 121 | + parser.add_argument("cache_file", help="Cache file to operate on") |
| 122 | + parser.add_argument( |
| 123 | + "item_ids", |
| 124 | + nargs="*", |
| 125 | + help="Item IDs to operate on when using item-related commands", |
| 126 | + ) |
| 127 | + |
| 128 | + args = parser.parse_args() |
| 129 | + |
| 130 | + # Check if more than one command option was supplied |
| 131 | + if "command" not in args or args.command is None: |
| 132 | + usage_error("One command option must be supplied.") |
| 133 | + elif ( |
| 134 | + len( |
| 135 | + { |
| 136 | + key |
| 137 | + for key, value in vars(args).items() |
| 138 | + if key == "command" and value is not None |
| 139 | + } |
| 140 | + ) |
| 141 | + > 1 |
| 142 | + ): |
| 143 | + usage_error("Only one command option may be supplied") |
| 144 | + |
| 145 | + # Handle missing cache_file |
| 146 | + if not args.cache_file: |
113 | 147 | usage_error("Missing expected cache filename") |
114 | | - elif want_ids and not len(ids): |
| 148 | + |
| 149 | + # Handle commands that require item IDs |
| 150 | + if args.command in ["item", "hide", "unhide"] and not args.item_ids: |
115 | 151 | usage_error("Missing expected entry ids") |
116 | 152 |
|
117 | 153 | # Open the cache file directly to get the URL it represents |
118 | 154 | try: |
119 | | - db = dbhash.open(cache_file) |
120 | | - url = db["url"] |
121 | | - db.close() |
122 | | - except dbhash.bsddb._db.DBError, e: |
123 | | - print >>sys.stderr, cache_file + ":", e.args[1] |
124 | | - sys.exit(1) |
| 155 | + with shelve.open(args.cache_file, "r") as db: |
| 156 | + url = db["url"] |
125 | 157 | except KeyError: |
126 | | - print >>sys.stderr, cache_file + ": Probably not a cache file" |
| 158 | + print(f"{args.cache_file}: Probably not a cache file", file=sys.stderr) |
| 159 | + sys.exit(1) |
| 160 | + except Exception as e: |
| 161 | + print(f"{args.cache_file}: {e!s}", file=sys.stderr) |
127 | 162 | sys.exit(1) |
128 | 163 |
|
129 | 164 | # Now do it the right way :-) |
130 | | - my_planet = planet.Planet(ConfigParser.ConfigParser()) |
131 | | - my_planet.cache_directory = os.path.dirname(cache_file) |
| 165 | + my_planet = planet.Planet(configparser.ConfigParser()) |
| 166 | + my_planet.cache_directory = os.path.dirname(args.cache_file) |
132 | 167 | channel = planet.Channel(my_planet, url) |
133 | 168 |
|
134 | | - for item_id in ids: |
| 169 | + for item_id in args.item_ids: |
135 | 170 | if not channel.has_item(item_id): |
136 | | - print >>sys.stderr, item_id + ": Not in channel" |
| 171 | + print(item_id + ": Not in channel", file=sys.stderr) |
137 | 172 | sys.exit(1) |
138 | 173 |
|
139 | 174 | # Do the user's bidding |
140 | | - if command == "channel": |
| 175 | + if args.command == "channel": |
141 | 176 | print_keys(channel, "Channel Keys") |
142 | 177 |
|
143 | | - elif command == "item": |
144 | | - for item_id in ids: |
| 178 | + elif args.command == "item": |
| 179 | + for item_id in args.item_ids: |
145 | 180 | item = channel.get_item(item_id) |
146 | 181 | print_keys(item, "Item Keys for %s" % item_id) |
147 | 182 |
|
148 | | - elif command == "list": |
149 | | - print "Items in Channel:" |
150 | | - for item in channel.items(hidden=1, sorted=1): |
151 | | - print " " + item.id |
152 | | - print " " + time.strftime(planet.TIMEFMT_ISO, item.date) |
| 183 | + elif args.command == "list": |
| 184 | + print("Items in Channel:") |
| 185 | + for item in channel.items(hidden=True, sorted=True): |
| 186 | + print(" " + item.id) |
| 187 | + print(" " + time.strftime(planet.TIMEFMT_ISO, item.date)) |
153 | 188 | if hasattr(item, "title"): |
154 | | - print " " + fit_str(item.title, 70) |
| 189 | + print(" " + fit_str(item.title, 70)) |
155 | 190 | if hasattr(item, "hidden"): |
156 | | - print " (hidden)" |
| 191 | + print(" (hidden)") |
157 | 192 |
|
158 | | - elif command == "keys": |
| 193 | + elif args.command == "keys": |
159 | 194 | keys = {} |
160 | 195 | for item in channel.items(): |
161 | | - for key in item.keys(): |
| 196 | + for key in item: |
162 | 197 | keys[key] = 1 |
163 | 198 |
|
164 | | - keys = keys.keys() |
165 | | - keys.sort() |
| 199 | + keys = sorted(keys.keys()) |
166 | 200 |
|
167 | | - print "Keys used in Channel:" |
| 201 | + print("Keys used in Channel:") |
168 | 202 | for key in keys: |
169 | | - print " " + key |
170 | | - print |
| 203 | + print(" " + key) |
| 204 | + print() |
171 | 205 |
|
172 | | - print "Use --item to output values of particular items." |
| 206 | + print("Use --item to output values of particular items.") |
173 | 207 |
|
174 | | - elif command == "hide": |
175 | | - for item_id in ids: |
| 208 | + elif args.command == "hide": |
| 209 | + for item_id in args.item_ids: |
176 | 210 | item = channel.get_item(item_id) |
177 | 211 | if hasattr(item, "hidden"): |
178 | | - print item_id + ": Already hidden." |
| 212 | + print(item_id + ": Already hidden.") |
179 | 213 | else: |
180 | 214 | item.hidden = "yes" |
181 | 215 |
|
182 | 216 | channel.cache_write() |
183 | | - print "Done." |
| 217 | + print("Done.") |
184 | 218 |
|
185 | | - elif command == "unhide": |
186 | | - for item_id in ids: |
| 219 | + elif args.command == "unhide": |
| 220 | + for item_id in args.item_ids: |
187 | 221 | item = channel.get_item(item_id) |
188 | 222 | if hasattr(item, "hidden"): |
189 | | - del(item.hidden) |
| 223 | + del item.hidden |
190 | 224 | else: |
191 | | - print item_id + ": Not hidden." |
| 225 | + print(item_id + ": Not hidden.") |
192 | 226 |
|
193 | 227 | channel.cache_write() |
194 | | - print "Done." |
| 228 | + print("Done.") |
0 commit comments