From 32ea20599342da7eeae1a844511dc4a953c11d5a Mon Sep 17 00:00:00 2001 From: oneyb Date: Tue, 24 Jul 2018 22:09:13 +0200 Subject: [PATCH] added json output with tests --- syncthingmanager/__init__.py | 247 +++++++++++++++++++++-------------- syncthingmanager/conftest.py | 13 +- 2 files changed, 164 insertions(+), 96 deletions(-) diff --git a/syncthingmanager/__init__.py b/syncthingmanager/__init__.py index edded38..77b52af 100644 --- a/syncthingmanager/__init__.py +++ b/syncthingmanager/__init__.py @@ -21,6 +21,7 @@ import pathlib import sys import os +import json from xml.etree.ElementTree import parse from textwrap import dedent import platform @@ -484,7 +485,7 @@ def db_folder_sync_fraction(self, folderstr): except TypeError: return 1 - def _print_device_info(self, devicestr): + def _print_device_info(self, devicestr, json_out=False): config = self.system.config() info = self.device_info(devicestr) try: @@ -492,18 +493,25 @@ def _print_device_info(self, devicestr): except TypeError: raise SyncthingManagerError("Device not configured: " + devicestr) folders = self.device_info(device['deviceID'])['folders'] - outstr = """\ - {0} - Addresses: {1} - Folders: {2} - ID: {3} - Introducer? {4} - """.format(device['name'], ', '.join(device['addresses']), - ', '.join(map(str, folders)), device['deviceID'], - device['introducer']) - print(dedent(outstr)) - - def _device_list(self): + if json_out: + out_dict = {} + out_dict[device['deviceID']] = device + out_dict[device['deviceID']]['folders'] = folders + sys.stdout.write(json.dumps(out_dict, indent=True)) + + else: + outstr = """\ + {0} + Addresses: {1} + Folders: {2} + ID: {3} + Introducer? {4} + """.format(device['name'], ', '.join(device['addresses']), + ', '.join(map(str, folders)), device['deviceID'], + device['introducer']) + print(dedent(outstr)) + + def _device_list(self, json_out=False): """Prints out a formatted list of devices and their state from the active configuration.""" config = self.system.config() @@ -520,34 +528,48 @@ def _device_list(self): continue else: not_connected.append(device) - outstr = """\ - {0} This Device - ID: {1} - """.format(this_device['name'], this_device['deviceID']) - print(dedent(outstr)) - for device in connected: - address = connections[device['deviceID']]['address'] - folders = self.device_info(device['deviceID'])['folders'] - outstr = """\ - {0} {1}Connected{2} - At: {3} - Folders: {4} - ID: {5} - """.format(device['name'], OKGREEN, ENDC, address, - ', '.join(map(str, folders)), device['deviceID']) - print(dedent(outstr)) - - for device in not_connected: - folders = self.device_info(device['deviceID'])['folders'] + if json_out: + out_dict = {} + out_dict[this_device['deviceID']] = this_device + out_dict.update(connections) + for device in connected: + out_dict[device['deviceID']]['folders'] = \ + self.device_info(device['deviceID'])['folders'] + + for device in not_connected: + out_dict[device['deviceID']]['folders'] = \ + self.device_info(device['deviceID'])['folders'] + + sys.stdout.write(json.dumps(out_dict, indent=True)) + else: outstr = """\ - {0} {1}Not Connected{2} - Folders: {3} - ID: {4} - """.format(device['name'], FAIL, ENDC, - ', '.join(map(str, folders)), device['deviceID']) + {0} This Device + ID: {1} + """.format(this_device['name'], this_device['deviceID']) print(dedent(outstr)) - - def _print_folder_info(self, folderstr): + for device in connected: + address = connections[device['deviceID']]['address'] + folders = self.device_info(device['deviceID'])['folders'] + outstr = """\ + {0} {1}Connected{2} + At: {3} + Folders: {4} + ID: {5} + """.format(device['name'], OKGREEN, ENDC, address, + ', '.join(map(str, folders)), device['deviceID']) + print(dedent(outstr)) + + for device in not_connected: + folders = self.device_info(device['deviceID'])['folders'] + outstr = """\ + {0} {1}Not Connected{2} + Folders: {3} + ID: {4} + """.format(device['name'], FAIL, ENDC, + ', '.join(map(str, folders)), device['deviceID']) + print(dedent(outstr)) + + def _print_folder_info(self, folderstr, json_out=True): info = self.folder_info(folderstr) config = self.system.config() try: @@ -562,70 +584,83 @@ def _print_folder_info(self, folderstr): continue name = self.device_info(device['deviceID'])['name'] devices.append(name) - if folder['label'] == '': - folderstr = folder['id'] + if json_out: + sys.stdout.write(json.dumps({folder['id']: folder}, indent=True)) else: - folderstr = folder['label'] - nondefaults = "" - if folder['rescanIntervalS'] != 60: - nondefaults += (' Rescan Interval: ' + - str(folder['rescanIntervalS'])) - if folder['type'] != 'readwrite': - nondefaults += ('\n Folder Type: ' + - folder['type']) - if folder['order'] != 'random': - nondefaults += ('\n File Pull Order: ' + - folder['order']) - if folder['versioning']['type'] != '': - nondefaults += ('\n Versioning: ' + - folder['versioning']['type']) - if folder['versioning']['type'] == 'trashcan': - nondefaults += ('\n Clean out after: ' + - folder['versioning']['params']['cleanoutDays']) - if folder['versioning']['type'] == 'simple': - nondefaults += ('\n Keep Versions: ' + - folder['versioning']['params']['keep']) - if folder['versioning']['type'] == 'staggered': - nondefaults += ('\n Versions Path: ' + - folder['versioning']['params']['versionsPath']) - if folder['versioning']['type'] == 'external': - nondefaults += ('\n Command: ' + - folder['versioning']['params']['command']) - outstr = """\ - {0} {4}% - Shared With: {1} - Folder ID: {2} - Folder Path: {3}\ - """.format(folderstr, ', '.join(map(str, devices)), - folder['id'], folder['path'], str(sync_status)) - print(dedent(outstr)) - print(nondefaults) - - - def _folder_list(self): - """Prints out a formatted list of folders from the configuration.""" - config = self.system.config() - status = self.system.status() - for folder in config['folders']: - devices = [] - sync_status = floor(100 * self.db_folder_sync_fraction(folder['id'])) - for device in folder['devices']: - if device['deviceID'] == status['myID']: - continue - name = self.device_info(device['deviceID'])['name'] - devices.append(name) if folder['label'] == '': folderstr = folder['id'] else: folderstr = folder['label'] + nondefaults = "" + if folder['rescanIntervalS'] != 60: + nondefaults += (' Rescan Interval: ' + + str(folder['rescanIntervalS'])) + if folder['type'] != 'readwrite': + nondefaults += ('\n Folder Type: ' + + folder['type']) + if folder['order'] != 'random': + nondefaults += ('\n File Pull Order: ' + + folder['order']) + if folder['versioning']['type'] != '': + nondefaults += ('\n Versioning: ' + + folder['versioning']['type']) + if folder['versioning']['type'] == 'trashcan': + nondefaults += ('\n Clean out after: ' + + folder['versioning']['params']['cleanoutDays']) + if folder['versioning']['type'] == 'simple': + nondefaults += ('\n Keep Versions: ' + + folder['versioning']['params']['keep']) + if folder['versioning']['type'] == 'staggered': + nondefaults += ('\n Versions Path: ' + + folder['versioning']['params']['versionsPath']) + if folder['versioning']['type'] == 'external': + nondefaults += ('\n Command: ' + + folder['versioning']['params']['command']) outstr = """\ {0} {4}% Shared With: {1} Folder ID: {2} - Folder Path: {3} + Folder Path: {3}\ """.format(folderstr, ', '.join(map(str, devices)), folder['id'], folder['path'], str(sync_status)) print(dedent(outstr)) + print(nondefaults) + + + def _folder_list(self, json_out=False): + """Prints out a formatted list of folders from the configuration.""" + config = self.system.config() + status = self.system.status() + if json_out: + out_dict = {} + for folder in config['folders']: + sync_status = floor(100 * self.db_folder_sync_fraction(folder['id'])) + devices = [] + for device in folder['devices']: + if device['deviceID'] == status['myID']: + continue + name = self.device_info(device['deviceID'])['name'] + devices.append(name) + if json_out: + out_dict[folder['id']] = folder + out_dict[folder['id']]['sync_status'] = sync_status + out_dict[folder['id']]['devices'] = devices + else: + if folder['label'] == '': + folderstr = folder['id'] + else: + folderstr = folder['label'] + outstr = """\ + {0} {4}% + Shared With: {1} + Folder ID: {2} + Folder Path: {3} + """.format(folderstr, ', '.join(map(str, devices)), + folder['id'], folder['path'], str(sync_status)) + print(dedent(outstr)) + if json_out: + sys.stdout.write(json.dumps(out_dict, indent=True)) + def arguments(): @@ -680,9 +715,14 @@ def arguments(): help="shows detailed device information") device_info_parser.add_argument('device', metavar='DEVICE', help="the device name or ID") + device_info_parser.add_argument('-j', '--json_out', action='store_true', + help="output to json") list_device_parser = device_subparsers.add_parser('list', help="shows a list of devices and some information") + list_device_parser.add_argument('-j', '--json_out', action='store_true', + help="output to json") + remove_device_parser = device_subparsers.add_parser('remove', help="remove a device") @@ -773,8 +813,13 @@ def arguments(): folder_info_parser = folder_subparsers.add_parser('info', help='show detailed information about a folder') folder_info_parser.add_argument('folder', metavar='FOLDER', help='the folder name or label') + folder_info_parser.add_argument('-j', '--json_out', action='store_true', + help="output to json") list_folder_parser = folder_subparsers.add_parser('list', help='show a list of configured folders') + list_folder_parser.add_argument('-j', '--json_out', action='store_true', + help="output to json") + return parser.parse_args() @@ -853,9 +898,15 @@ def main(): elif args.deviceparser_name == 'remove': st.remove_device(args.device) elif args.deviceparser_name == 'info': - st._print_device_info(args.device) + if args.json_out: + st._print_device_info(args.device, json_out=True) + else: + st._print_device_info(args.device) elif args.deviceparser_name == 'list': - st._device_list() + if args.json_out: + st._device_list(json_out=True) + else: + st._device_list() elif args.deviceparser_name == 'edit': if args.name: st.device_change_name(args.device, args.name) @@ -913,9 +964,15 @@ def main(): elif args.versionparser_name == 'none': st.folder_setup_versioning_none(args.folder) elif args.folderparser_name == 'info': - st._print_folder_info(args.folder) + if args.json_out: + st._print_folder_info(args.folder, json_out=True) + else: + st._print_folder_info(args.folder) elif args.folderparser_name == 'list': - st._folder_list() + if args.json_out: + st._folder_list(json_out=True) + else: + st._folder_list() except SyncthingError as err: print(err) sys.exit(1) diff --git a/syncthingmanager/conftest.py b/syncthingmanager/conftest.py index cc65eb3..c7e83c6 100644 --- a/syncthingmanager/conftest.py +++ b/syncthingmanager/conftest.py @@ -1,5 +1,16 @@ import syncthingmanager as stman import pytest +import os + + +# classicsc +test_deviceID = 'MFZWI3D-BONSGYC-YLTMRWG-C43ENR5-QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD' + +# oneyb +if os.getenv('USER') == 'oney': + test_deviceID = \ + 'MH3SMD5-Q66HTXW-YXD77D4-JT3UJPF-APV5KPQ-REZBQWI-QQYNSSV-RGGRSQW' + @pytest.fixture(scope='session') def temp_folder(tmpdir_factory): @@ -11,7 +22,7 @@ def s(request, temp_folder): s = stman.SyncthingManager(APIInfo['APIkey'], APIInfo['Hostname'], APIInfo['Port']) cfg = s.system.config() cfga = s.system.config() - test_device = {'deviceID': 'MFZWI3D-BONSGYC-YLTMRWG-C43ENR5-QXGZDMM-FZWI3DP-BONSGYY-LTMRWAD', + test_device = {'deviceID': test_deviceID, 'name': 'SyncthingManagerTestDevice1', 'addresses': ['localhost']} test_folder = {'id': 'stmantest1', 'label': 'SyncthingManagerTestFolder1', 'path': str(temp_folder), 'type': 'readwrite', 'rescanIntervalS': 60,