Changeset View
Changeset View
Standalone View
Standalone View
swh/graph/cli.py
Show First 20 Lines • Show All 41 Lines • ▼ Show 20 Lines | |||||
def dump_pid2int(filename): | def dump_pid2int(filename): | ||||
for (pid, int) in PidToIntMap(filename): | for (pid, int) in PidToIntMap(filename): | ||||
print('{}\t{}'.format(pid, int)) | print('{}\t{}'.format(pid, int)) | ||||
def dump_int2pid(filename): | def dump_int2pid(filename): | ||||
for (int, pid) in enumerate(IntToPidMap(filename)): | for (int, pid) in IntToPidMap(filename): | ||||
print('{}\t{}'.format(int, pid)) | print('{}\t{}'.format(int, pid)) | ||||
def restore_pid2int(filename): | def restore_pid2int(filename): | ||||
"""read a textual PID->int map from stdin and write its binary version to | """read a textual PID->int map from stdin and write its binary version to | ||||
filename | filename | ||||
""" | """ | ||||
with open(filename, 'wb') as dst: | with open(filename, 'wb') as dst: | ||||
for line in sys.stdin: | for line in sys.stdin: | ||||
(str_pid, str_int) = line.split() | (str_pid, str_int) = line.split() | ||||
PidToIntMap.write_record(dst, str_pid, int(str_int)) | PidToIntMap.write_record(dst, str_pid, int(str_int)) | ||||
def restore_int2pid(filename): | def restore_int2pid(filename, length): | ||||
"""read a textual int->PID map from stdin and write its binary version to | """read a textual int->PID map from stdin and write its binary version to | ||||
filename | filename | ||||
""" | """ | ||||
with open(filename, 'wb') as dst: | int2pid = IntToPidMap(filename, mode='wb', length=length) | ||||
for line in sys.stdin: | for line in sys.stdin: | ||||
(str_int, str_pid) = line.split() | (str_int, str_pid) = line.split() | ||||
dst.seek(int(str_int) * PID_BIN_SIZE) | int2pid[int(str_int)] = str_pid | ||||
IntToPidMap.write_record(dst, str_pid) | int2pid.close() | ||||
@map.command('dump') | @map.command('dump') | ||||
@click.option('--type', '-t', 'map_type', required=True, | @click.option('--type', '-t', 'map_type', required=True, | ||||
type=click.Choice(['pid2int', 'int2pid']), | type=click.Choice(['pid2int', 'int2pid']), | ||||
help='type of map to dump') | help='type of map to dump') | ||||
@click.argument('filename', required=True, type=click.Path(exists=True)) | @click.argument('filename', required=True, type=click.Path(exists=True)) | ||||
@click.pass_context | @click.pass_context | ||||
def dump_map(ctx, map_type, filename): | def dump_map(ctx, map_type, filename): | ||||
"""dump a binary PID<->int map to textual format""" | """dump a binary PID<->int map to textual format""" | ||||
if map_type == 'pid2int': | if map_type == 'pid2int': | ||||
dump_pid2int(filename) | dump_pid2int(filename) | ||||
elif map_type == 'int2pid': | elif map_type == 'int2pid': | ||||
dump_int2pid(filename) | dump_int2pid(filename) | ||||
else: | else: | ||||
raise ValueError('invalid map type: ' + map_type) | raise ValueError('invalid map type: ' + map_type) | ||||
pass | pass | ||||
@map.command('restore') | @map.command('restore') | ||||
@click.option('--type', '-t', 'map_type', required=True, | @click.option('--type', '-t', 'map_type', required=True, | ||||
type=click.Choice(['pid2int', 'int2pid']), | type=click.Choice(['pid2int', 'int2pid']), | ||||
help='type of map to dump') | help='type of map to dump') | ||||
@click.option('--length', '-l', type=int, | |||||
help='''map size in number of logical records | |||||
(required for int2pid maps)''') | |||||
douardda: This is not part of the diff, but I tend to find weird to use //required// **options** in a cli… | |||||
Done Inline ActionsThat's a fair point. But when you start having multiple positional argument, it's a pain to remember which one goes where if there isn't an obvious order (e.g., cp's src/dst). So I'd rather keep it like this for now. zack: That's a fair point. But when you start having multiple positional argument, it's a pain to… | |||||
@click.argument('filename', required=True, type=click.Path()) | @click.argument('filename', required=True, type=click.Path()) | ||||
@click.pass_context | @click.pass_context | ||||
def restore_map(ctx, map_type, filename): | def restore_map(ctx, map_type, length, filename): | ||||
"""restore a binary PID<->int map from textual format""" | """restore a binary PID<->int map from textual format""" | ||||
if map_type == 'pid2int': | if map_type == 'pid2int': | ||||
restore_pid2int(filename) | restore_pid2int(filename, length) | ||||
elif map_type == 'int2pid': | elif map_type == 'int2pid': | ||||
restore_int2pid(filename) | if length is None: | ||||
raise click.UsageError( | |||||
'map length is required when restoring {} maps'.format( | |||||
map_type), ctx) | |||||
restore_int2pid(filename, length) | |||||
else: | else: | ||||
raise ValueError('invalid map type: ' + map_type) | raise ValueError('invalid map type: ' + map_type) | ||||
def main(): | def main(): | ||||
return cli(auto_envvar_prefix='SWH_GRAPH') | return cli(auto_envvar_prefix='SWH_GRAPH') | ||||
if __name__ == '__main__': | if __name__ == '__main__': | ||||
main() | main() |
This is not part of the diff, but I tend to find weird to use required options in a cli tool...
This should be an argument IMHO. Or at least let the option have a default value.