mirror of
https://github.com/rclone/rclone.git
synced 2024-12-26 00:49:22 +01:00
185 lines
5.7 KiB
Python
185 lines
5.7 KiB
Python
|
#!/usr/bin/env python3
|
||
|
"""
|
||
|
Test program to demonstrate the remote config interfaces in
|
||
|
rclone.
|
||
|
|
||
|
This program can simulate
|
||
|
|
||
|
rclone config create
|
||
|
rclone config update
|
||
|
rclone config password - NOT implemented yet
|
||
|
rclone authorize - NOT implemented yet
|
||
|
|
||
|
Pass the desired action as the first argument then any parameters.
|
||
|
|
||
|
This assumes passwords will be passed in the clear.
|
||
|
"""
|
||
|
|
||
|
import argparse
|
||
|
import subprocess
|
||
|
import json
|
||
|
from pprint import pprint
|
||
|
|
||
|
sep = "-"*60
|
||
|
|
||
|
def rpc(command, params):
|
||
|
"""
|
||
|
Run the command. This could be either over the CLI or the API.
|
||
|
Here we run over the API using rclone rc --loopback which is
|
||
|
useful for making sure state is saved properly.
|
||
|
"""
|
||
|
cmd = ["rclone", "-vv", "rc", "--loopback", command, "--json", json.dumps(params)]
|
||
|
result = subprocess.run(cmd, stdout=subprocess.PIPE, check=True)
|
||
|
return json.loads(result.stdout)
|
||
|
|
||
|
def parse_parameters(parameters):
|
||
|
"""
|
||
|
Parse the incoming key=value parameters into a dict
|
||
|
"""
|
||
|
d = {}
|
||
|
for param in parameters:
|
||
|
parts = param.split("=", 1)
|
||
|
if len(parts) != 2:
|
||
|
raise ValueError("bad format for parameter need name=value")
|
||
|
d[parts[0]] = parts[1]
|
||
|
return d
|
||
|
|
||
|
def ask(opt):
|
||
|
"""
|
||
|
Ask the user to enter the option
|
||
|
|
||
|
This is the user interface for asking a user a question.
|
||
|
|
||
|
If there are examples they should be presented.
|
||
|
"""
|
||
|
while True:
|
||
|
if opt["IsPassword"]:
|
||
|
print("*** Inputting a password")
|
||
|
print(opt['Help'])
|
||
|
examples = opt.get("Examples", ())
|
||
|
or_number = ""
|
||
|
if len(examples) > 0:
|
||
|
or_number = " or choice number"
|
||
|
for i, example in enumerate(examples):
|
||
|
print(f"{i:3} value: {example['Value']}")
|
||
|
print(f" help: {example['Help']}")
|
||
|
print(f"Enter a {opt['Type']} value{or_number}. Press Enter for the default ('{opt['DefaultStr']}')")
|
||
|
print(f"{opt['Name']}> ", end='')
|
||
|
s = input()
|
||
|
if s == "":
|
||
|
return opt["DefaultStr"]
|
||
|
try:
|
||
|
i = int(s)
|
||
|
if i >= 0 and i < len(examples):
|
||
|
return examples[i]["Value"]
|
||
|
except ValueError:
|
||
|
pass
|
||
|
if opt["Exclusive"]:
|
||
|
for example in examples:
|
||
|
if s == example["Value"]:
|
||
|
return s
|
||
|
# Exclusive is set but the value isn't one of the accepted
|
||
|
# ones so continue
|
||
|
print("Value isn't one of the acceptable values")
|
||
|
else:
|
||
|
return s
|
||
|
return s
|
||
|
|
||
|
def create_or_update(what, args):
|
||
|
"""
|
||
|
Run the equivalent of rclone config create
|
||
|
or rclone config update
|
||
|
|
||
|
what should either be "create" or "update
|
||
|
"""
|
||
|
print(what, args)
|
||
|
params = parse_parameters(args.parameters)
|
||
|
inp = {
|
||
|
"name": args.name,
|
||
|
"parameters": params,
|
||
|
"opt": {
|
||
|
"nonInteractive": True,
|
||
|
"all": args.all,
|
||
|
"noObscure": args.obscured_passwords,
|
||
|
"obscure": not args.obscured_passwords,
|
||
|
},
|
||
|
}
|
||
|
if what == "create":
|
||
|
inp["type"] = args.type
|
||
|
while True:
|
||
|
print(sep)
|
||
|
print("Input to API")
|
||
|
pprint(inp)
|
||
|
print(sep)
|
||
|
out = rpc("config/"+what, inp)
|
||
|
print(sep)
|
||
|
print("Output from API")
|
||
|
pprint(out)
|
||
|
print(sep)
|
||
|
if out["State"] == "":
|
||
|
return
|
||
|
if out["Error"]:
|
||
|
print("Error", out["Error"])
|
||
|
result = ask(out["Option"])
|
||
|
inp["opt"]["state"] = out["State"]
|
||
|
inp["opt"]["result"] = result
|
||
|
inp["opt"]["continue"] = True
|
||
|
|
||
|
def create(args):
|
||
|
"""Run the equivalent of rclone config create"""
|
||
|
create_or_update("create", args)
|
||
|
|
||
|
def update(args):
|
||
|
"""Run the equivalent of rclone config update"""
|
||
|
create_or_update("update", args)
|
||
|
|
||
|
def password(args):
|
||
|
"""Run the equivalent of rclone config password"""
|
||
|
print("password", args)
|
||
|
raise NotImplementedError()
|
||
|
|
||
|
def authorize(args):
|
||
|
"""Run the equivalent of rclone authorize"""
|
||
|
print("authorize", args)
|
||
|
raise NotImplementedError()
|
||
|
|
||
|
def main():
|
||
|
"""
|
||
|
Make the command line parser and dispatch
|
||
|
"""
|
||
|
parser = argparse.ArgumentParser(
|
||
|
description=__doc__,
|
||
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
||
|
)
|
||
|
parser.add_argument("-a", "--all", action='store_true',
|
||
|
help="Ask all the config questions if set")
|
||
|
parser.add_argument("-o", "--obscured-passwords", action='store_true',
|
||
|
help="If set assume the passwords are obscured")
|
||
|
|
||
|
subparsers = parser.add_subparsers(dest='command', required=True)
|
||
|
|
||
|
subparser = subparsers.add_parser('create')
|
||
|
subparser.add_argument("name", type=str, help="Name of remote to create")
|
||
|
subparser.add_argument("type", type=str, help="Type of remote to create")
|
||
|
subparser.add_argument("parameters", type=str, nargs='*', help="Config parameters name=value name=value")
|
||
|
subparser.set_defaults(func=create)
|
||
|
|
||
|
subparser = subparsers.add_parser('update')
|
||
|
subparser.add_argument("name", type=str, help="Name of remote to update")
|
||
|
subparser.add_argument("parameters", type=str, nargs='*', help="Config parameters name=value name=value")
|
||
|
subparser.set_defaults(func=update)
|
||
|
|
||
|
subparser = subparsers.add_parser('password')
|
||
|
subparser.add_argument("name", type=str, help="Name of remote to update")
|
||
|
subparser.add_argument("parameters", type=str, nargs='*', help="Config parameters name=value name=value")
|
||
|
subparser.set_defaults(func=password)
|
||
|
|
||
|
subparser = subparsers.add_parser('authorize')
|
||
|
subparser.set_defaults(func=authorize)
|
||
|
|
||
|
args = parser.parse_args()
|
||
|
args.func(args)
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
main()
|