From 0988389972aed2e8501ef8f4bfdec9f4a20e00e1 Mon Sep 17 00:00:00 2001 From: Tom Willemse Date: Sun, 15 Dec 2013 22:45:06 +0100 Subject: [PATCH] Add check command, remove _ast import - The check command checks to see if there is anything missing from the specified output file. - All types in the `_ast' module are also exported from the `ast' module, so there is no need to use `_ast' explicitly. - Don't raise an exception when a value from the specification doesn't match a predicate, the `check' command will take care of this. - Place some functions outside of their previous classes. These are used by several classes/methods and they need no state from these classes. --- topple/topple.py | 74 ++++++++++++++++++++++++++++++------------------ 1 file changed, 46 insertions(+), 28 deletions(-) diff --git a/topple/topple.py b/topple/topple.py index 5a52e45..88a2bd0 100644 --- a/topple/topple.py +++ b/topple/topple.py @@ -1,6 +1,5 @@ from __future__ import print_function -import _ast import ast import os import os.path @@ -21,12 +20,34 @@ def write_settings(specs, out, values=None): .format(file=specs.OUTPUT_FILE), file=out) for key, spec in specs.SETTINGS: - value = values.get(key, spec['initial']) + value = values.get(key, spec[1]) + print(key, repr(value), sep=' = ', file=out) - if (spec['predicate'](value)): - print(key, repr(value), sep=' = ', file=out) - else: - raise RuntimeError('Invalid type for %s: %s' % (key, repr(value))) + +def get_node_value(node): + if isinstance(node, ast.Name): + return ast.literal_eval(node.id) + elif isinstance(node, ast.Str): + return node.s + elif isinstance(node, ast.Num): + return node.n + else: + return node + + +def get_settings_from(filename): + res = {} + + with open(filename, 'r') as f: + tree = ast.parse('\n'.join(f.readlines()), filename) + for node in ast.iter_child_nodes(tree): + if isinstance(node, ast.Assign): + for target in node.targets: + res[target.id] = get_node_value(node.value) + else: + print(node, node._fields) + + return res class PreviewMixin(object): @@ -62,35 +83,29 @@ class Generate(pycommand.CommandBase, PreviewMixin): class Update(pycommand.CommandBase, PreviewMixin): usagestr = 'usage: topple update [--preview|-p]' - def _get_value(self, node): - if isinstance(node, _ast.Name): - return eval(node.id) - elif isinstance(node, _ast.Str): - return node.s - elif isinstance(node, _ast.Num): - return node.n - else: - return node + def run(self): + sys.path.insert(0, os.getcwd()) + filename = 'settings_local.py' + res = get_settings_from(filename) + specs = get_setting_specs(self.parentFlags['module'] or 'toppler') + self.write(specs.OUTPUT_FILE, specs, res) - def _get_values(self, filename): - res = {} - with open(filename, 'r') as f: - tree = ast.parse('\n'.join(f.readlines()), filename) - for node in ast.iter_child_nodes(tree): - if isinstance(node, _ast.Assign): - res[node.targets[0].id] = self._get_value(node.value) - else: - print(node, node._fields) - - return res +class Check(pycommand.CommandBase): + usagestr = 'usage: topple check' def run(self): sys.path.insert(0, os.getcwd()) filename = 'settings_local.py' - res = self._get_values(filename) + res = get_settings_from(filename) specs = get_setting_specs(self.parentFlags['module'] or 'toppler') - self.write(specs.OUTPUT_FILE, specs, res) + + for key, spec in specs.SETTINGS: + if key not in res: + print('Missing setting:', key) + elif not spec[0](res[key]): + print('Value "%s" for %s does not pass predicate `%s\'' + % (res[key], key, spec[0].func_name)) class Topple(pycommand.CommandBase): @@ -99,6 +114,7 @@ class Topple(pycommand.CommandBase): 'Commands:\n' ' generate Generate a new settings file.\n' ' update Update an existing settings file.\n' + ' check Check the validity of an existing settings file.' ) optionList = (('module', ('m', '', 'Use specified python module.')),) @@ -117,6 +133,8 @@ class Topple(pycommand.CommandBase): cmd = Generate(argv=self.args[1:]) elif self.args[0] == 'update': cmd = Update(argv=self.args[1:]) + elif self.args[0] == 'check': + cmd = Check(argv=self.args[1:]) else: print('Undefined command: {cmd}'.format(cmd=self.args[0])) return 1