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.
This commit is contained in:
parent
ea8763fd0d
commit
0988389972
1 changed files with 46 additions and 28 deletions
|
@ -1,6 +1,5 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import _ast
|
|
||||||
import ast
|
import ast
|
||||||
import os
|
import os
|
||||||
import os.path
|
import os.path
|
||||||
|
@ -21,12 +20,34 @@ def write_settings(specs, out, values=None):
|
||||||
.format(file=specs.OUTPUT_FILE), file=out)
|
.format(file=specs.OUTPUT_FILE), file=out)
|
||||||
|
|
||||||
for key, spec in specs.SETTINGS:
|
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)
|
def get_node_value(node):
|
||||||
else:
|
if isinstance(node, ast.Name):
|
||||||
raise RuntimeError('Invalid type for %s: %s' % (key, repr(value)))
|
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):
|
class PreviewMixin(object):
|
||||||
|
@ -62,35 +83,29 @@ class Generate(pycommand.CommandBase, PreviewMixin):
|
||||||
class Update(pycommand.CommandBase, PreviewMixin):
|
class Update(pycommand.CommandBase, PreviewMixin):
|
||||||
usagestr = 'usage: topple update [--preview|-p]'
|
usagestr = 'usage: topple update [--preview|-p]'
|
||||||
|
|
||||||
def _get_value(self, node):
|
def run(self):
|
||||||
if isinstance(node, _ast.Name):
|
sys.path.insert(0, os.getcwd())
|
||||||
return eval(node.id)
|
filename = 'settings_local.py'
|
||||||
elif isinstance(node, _ast.Str):
|
res = get_settings_from(filename)
|
||||||
return node.s
|
specs = get_setting_specs(self.parentFlags['module'] or 'toppler')
|
||||||
elif isinstance(node, _ast.Num):
|
self.write(specs.OUTPUT_FILE, specs, res)
|
||||||
return node.n
|
|
||||||
else:
|
|
||||||
return node
|
|
||||||
|
|
||||||
def _get_values(self, filename):
|
|
||||||
res = {}
|
|
||||||
|
|
||||||
with open(filename, 'r') as f:
|
class Check(pycommand.CommandBase):
|
||||||
tree = ast.parse('\n'.join(f.readlines()), filename)
|
usagestr = 'usage: topple check'
|
||||||
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
|
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
sys.path.insert(0, os.getcwd())
|
sys.path.insert(0, os.getcwd())
|
||||||
filename = 'settings_local.py'
|
filename = 'settings_local.py'
|
||||||
res = self._get_values(filename)
|
res = get_settings_from(filename)
|
||||||
specs = get_setting_specs(self.parentFlags['module'] or 'toppler')
|
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):
|
class Topple(pycommand.CommandBase):
|
||||||
|
@ -99,6 +114,7 @@ class Topple(pycommand.CommandBase):
|
||||||
'Commands:\n'
|
'Commands:\n'
|
||||||
' generate Generate a new settings file.\n'
|
' generate Generate a new settings file.\n'
|
||||||
' update Update an existing settings file.\n'
|
' update Update an existing settings file.\n'
|
||||||
|
' check Check the validity of an existing settings file.'
|
||||||
)
|
)
|
||||||
optionList = (('module', ('m', '<modulename>',
|
optionList = (('module', ('m', '<modulename>',
|
||||||
'Use specified python module.')),)
|
'Use specified python module.')),)
|
||||||
|
@ -117,6 +133,8 @@ class Topple(pycommand.CommandBase):
|
||||||
cmd = Generate(argv=self.args[1:])
|
cmd = Generate(argv=self.args[1:])
|
||||||
elif self.args[0] == 'update':
|
elif self.args[0] == 'update':
|
||||||
cmd = Update(argv=self.args[1:])
|
cmd = Update(argv=self.args[1:])
|
||||||
|
elif self.args[0] == 'check':
|
||||||
|
cmd = Check(argv=self.args[1:])
|
||||||
else:
|
else:
|
||||||
print('Undefined command: {cmd}'.format(cmd=self.args[0]))
|
print('Undefined command: {cmd}'.format(cmd=self.args[0]))
|
||||||
return 1
|
return 1
|
||||||
|
|
Loading…
Reference in a new issue