Initial commit
This commit is contained in:
commit
ea8763fd0d
5 changed files with 148 additions and 0 deletions
1
requirements.txt
Normal file
1
requirements.txt
Normal file
|
@ -0,0 +1 @@
|
|||
pycommand==0.1.0
|
13
scripts/topple
Executable file
13
scripts/topple
Executable file
|
@ -0,0 +1,13 @@
|
|||
#!/usr/bin/env python
|
||||
|
||||
import sys
|
||||
|
||||
import topple.topple
|
||||
|
||||
if __name__ == '__main__':
|
||||
cmd = topple.topple.Topple(sys.argv[1:])
|
||||
if cmd.error:
|
||||
print('error: {0}'.format(cmd.error))
|
||||
sys.exit(1)
|
||||
else:
|
||||
sys.exit(cmd.run())
|
2
topple/.gitignore
vendored
Normal file
2
topple/.gitignore
vendored
Normal file
|
@ -0,0 +1,2 @@
|
|||
__pycache__/
|
||||
*.pyc
|
1
topple/__init__.py
Normal file
1
topple/__init__.py
Normal file
|
@ -0,0 +1 @@
|
|||
|
131
topple/topple.py
Normal file
131
topple/topple.py
Normal file
|
@ -0,0 +1,131 @@
|
|||
from __future__ import print_function
|
||||
|
||||
import _ast
|
||||
import ast
|
||||
import os
|
||||
import os.path
|
||||
import sys
|
||||
|
||||
import pycommand
|
||||
|
||||
|
||||
def get_setting_specs(module):
|
||||
sys.path.insert(0, os.getcwd())
|
||||
return __import__(module)
|
||||
|
||||
|
||||
def write_settings(specs, out, values=None):
|
||||
values = values or {}
|
||||
|
||||
print('# {file} file generated by topple'
|
||||
.format(file=specs.OUTPUT_FILE), file=out)
|
||||
|
||||
for key, spec in specs.SETTINGS:
|
||||
value = values.get(key, spec['initial'])
|
||||
|
||||
if (spec['predicate'](value)):
|
||||
print(key, repr(value), sep=' = ', file=out)
|
||||
else:
|
||||
raise RuntimeError('Invalid type for %s: %s' % (key, repr(value)))
|
||||
|
||||
|
||||
class PreviewMixin(object):
|
||||
optionList = (
|
||||
('preview', ('p', None, 'Print generated file to stdout')),
|
||||
)
|
||||
|
||||
def __new__(cls, *args, **kwargs):
|
||||
cls.optionList = (cls.optionList or tuple()) + PreviewMixin.optionList
|
||||
instance = super(PreviewMixin, cls).__new__(cls, *args, **kwargs)
|
||||
return instance
|
||||
|
||||
def write(self, output, specs, values=None):
|
||||
preview = self.flags['preview']
|
||||
|
||||
if not preview:
|
||||
with open(output, 'w') as f:
|
||||
write_settings(specs, f, values)
|
||||
else:
|
||||
write_settings(specs, sys.stdout, values)
|
||||
|
||||
|
||||
class Generate(pycommand.CommandBase, PreviewMixin):
|
||||
usagestr = 'usage: topple generate [--preview|-p]'
|
||||
|
||||
def run(self):
|
||||
sys.path.insert(0, os.getcwd())
|
||||
|
||||
specs = get_setting_specs(self.parentFlags['module'] or 'toppler')
|
||||
self.write(specs.OUTPUT_FILE, specs)
|
||||
|
||||
|
||||
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 _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
|
||||
|
||||
def run(self):
|
||||
sys.path.insert(0, os.getcwd())
|
||||
filename = 'settings_local.py'
|
||||
res = self._get_values(filename)
|
||||
specs = get_setting_specs(self.parentFlags['module'] or 'toppler')
|
||||
self.write(specs.OUTPUT_FILE, specs, res)
|
||||
|
||||
|
||||
class Topple(pycommand.CommandBase):
|
||||
usagestr = 'usage: topple [--module=modulename|-m modulename] generate'
|
||||
description = (
|
||||
'Commands:\n'
|
||||
' generate Generate a new settings file.\n'
|
||||
' update Update an existing settings file.\n'
|
||||
)
|
||||
optionList = (('module', ('m', '<modulename>',
|
||||
'Use specified python module.')),)
|
||||
|
||||
def run(self):
|
||||
module = self.flags['module'] or 'toppler'
|
||||
|
||||
if not os.path.exists(module + '.py'):
|
||||
print('No {module}.py module found!'.format(module=module))
|
||||
return 1
|
||||
if not self.args:
|
||||
print(self.usage)
|
||||
return 2
|
||||
|
||||
if self.args[0] == 'generate':
|
||||
cmd = Generate(argv=self.args[1:])
|
||||
elif self.args[0] == 'update':
|
||||
cmd = Update(argv=self.args[1:])
|
||||
else:
|
||||
print('Undefined command: {cmd}'.format(cmd=self.args[0]))
|
||||
return 1
|
||||
|
||||
cmd.registerParentFlag('module', self.flags['module'])
|
||||
|
||||
if cmd.error:
|
||||
print('Error during {cmd}: {err}'.format(cmd=self.args[0],
|
||||
err=cmd.error))
|
||||
return 1
|
||||
else:
|
||||
return cmd.run()
|
Loading…
Reference in a new issue