|
9 | 9 | key: <timestamp> data |
10 | 10 |
|
11 | 11 | where <timestamp> is the human readable __timestamp decoded from the |
12 | | -data object. |
| 12 | +data object. Data object is dumped in json format. With pretty print |
13 | 13 |
|
| 14 | + key: |
| 15 | + <timestamp> |
| 16 | + { |
| 17 | + key: val, |
| 18 | + ... |
| 19 | + } |
| 20 | +
|
| 21 | +if data is not a python object, print will be key: data or |
| 22 | + key: |
| 23 | + data |
| 24 | +
|
| 25 | +if pretty printed. |
14 | 26 | """ |
15 | 27 |
|
16 | | -import dbm, marshal, sys |
| 28 | +import argparse, dbm, json, marshal, os, sys |
17 | 29 | from datetime import datetime |
18 | 30 |
|
19 | | -try: |
20 | | - file = sys.argv[1] |
21 | | -except IndexError: |
| 31 | +def indent(text, amount, ch=" "): |
| 32 | + """ Found at: https://stackoverflow.com/a/8348914 |
| 33 | + """ |
| 34 | + padding = amount * ch |
| 35 | + return ''.join(padding+line for line in text.splitlines(True)) |
| 36 | + |
| 37 | +def print_marshal(k): |
| 38 | + d = marshal.loads(db[k]) |
| 39 | + try: |
| 40 | + t = datetime.fromtimestamp(d['__timestamp']) |
| 41 | + except (KeyError, TypeError): |
| 42 | + # TypeError raised if marshalled data is not a dict (list, tuple etc) |
| 43 | + t = "no_timestamp" |
| 44 | + if args.pretty: |
| 45 | + print("%s:\n %s\n%s"%(k, t, indent(json.dumps( |
| 46 | + d, sort_keys=True, indent=4), 4))) |
| 47 | + else: |
| 48 | + print("%s: %s %s"%(k, t, d)) |
| 49 | + |
| 50 | +def print_raw(k): |
| 51 | + if args.pretty: |
| 52 | + print("%s:\n %s"%(k, db[k])) |
| 53 | + else: |
| 54 | + print("%s: %s"%(k, db[k])) |
| 55 | + |
| 56 | +parser = argparse.ArgumentParser( |
| 57 | + description='Dump DBM files used by Roundup in storage order.') |
| 58 | +parser.add_argument('-k', '--key', action="append", |
| 59 | + help='dump the entry for a key, can be used multiple times.') |
| 60 | +parser.add_argument('-K', '--keysonly', action='store_true', |
| 61 | + help='print the database keys, sorted in byte order.') |
| 62 | +parser.add_argument('-p', '--pretty', action='store_true', |
| 63 | + help='pretty print the output rather than printing on one line.') |
| 64 | +parser.add_argument('file', nargs='?', |
| 65 | + help='file to be dumped ("sessions" if not provided)') |
| 66 | +args = parser.parse_args() |
| 67 | + |
| 68 | +if args.file: |
| 69 | + file = args.file |
| 70 | +else: |
22 | 71 | file="sessions" |
23 | 72 |
|
24 | 73 | try: |
25 | 74 | db = dbm.open(file) |
26 | | -except Exception: |
27 | | - print("Unable to open database: %s"%file) |
28 | | - exit(1) |
| 75 | +except Exception as e: |
| 76 | + print("Unable to open database for %s: %s"%(file, e)) |
| 77 | + try: |
| 78 | + os.stat(file) |
| 79 | + print(" perhaps file is invalid or was created with a different version of Python?") |
| 80 | + except OSError: |
| 81 | + # the file does exist on disk. |
| 82 | + pass |
| 83 | + exit(1) |
| 84 | + |
| 85 | +if args.keysonly: |
| 86 | + for k in sorted(db.keys()): |
| 87 | + print("%s"%k) |
| 88 | + exit(0) |
| 89 | + |
| 90 | +if args.key: |
| 91 | + for k in args.key: |
| 92 | + try: |
| 93 | + print_marshal(k) |
| 94 | + except (ValueError): |
| 95 | + print_raw(k) |
| 96 | + exit(0) |
29 | 97 |
|
30 | 98 | k = db.firstkey() |
31 | 99 | while k is not None: |
32 | | - d = marshal.loads(db[k]) |
33 | | - t = datetime.fromtimestamp(d['__timestamp']) |
34 | | - print("%s: %s %s"%(k, t, d)) |
35 | | - k = db.nextkey(k) |
| 100 | + try: |
| 101 | + print_marshal(k) |
| 102 | + except (ValueError): # ValueError marshal.loads failed |
| 103 | + print_raw(k) |
| 104 | + |
| 105 | + k = db.nextkey(k) |
0 commit comments