| 1 |
"""usage: %prog [-Rr][-d][-I] files or pkg_resouces |
|---|
| 2 |
|
|---|
| 3 |
compiler front end. Use this to test & develop your command sets or as example |
|---|
| 4 |
code, see formtable.tool.py` to develop your own tools. |
|---|
| 5 |
|
|---|
| 6 |
`pgk_resources` should be listed as `requirement:resource` or just `resource`. |
|---|
| 7 |
If you use the later you must specify the requirement, used for all, using `-R`. |
|---|
| 8 |
|
|---|
| 9 |
`files` are just filesystem paths. |
|---|
| 10 |
|
|---|
| 11 |
`-I` will drop you into a very limited interactive shell. The banner will |
|---|
| 12 |
indicate the results, and hence the recognisable forms, gleaned from your |
|---|
| 13 |
argument sources. |
|---|
| 14 |
|
|---|
| 15 |
If `-I` is not specified the tool attempts to read from the standard input. |
|---|
| 16 |
|
|---|
| 17 |
|
|---|
| 18 |
non interactive use:: |
|---|
| 19 |
|
|---|
| 20 |
cat sample_input | freeformc .freeform/data/session.ffb |
|---|
| 21 |
|
|---|
| 22 |
interactive use:: |
|---|
| 23 |
|
|---|
| 24 |
freeformc -I ./freeform/data/session.ffb |
|---|
| 25 |
|
|---|
| 26 |
or substitute your own sources for `session.ffb`. The extention is not magic |
|---|
| 27 |
in any way. |
|---|
| 28 |
""" |
|---|
| 29 |
|
|---|
| 30 |
__all__=[ |
|---|
| 31 |
'compile_tool', |
|---|
| 32 |
'compile_aggregate_resources', 'compile_aggregate_files', |
|---|
| 33 |
|
|---|
| 34 |
'add_options_compile_tool' |
|---|
| 35 |
] |
|---|
| 36 |
import sys, optparse |
|---|
| 37 |
try: |
|---|
| 38 |
import pkg_resources |
|---|
| 39 |
except ImportError: |
|---|
| 40 |
pkg_resources = None |
|---|
| 41 |
from pprint import pprint |
|---|
| 42 |
from freeform.match import * |
|---|
| 43 |
from freeform.formtable import * |
|---|
| 44 |
|
|---|
| 45 |
def add_options_compile_tool(parser): |
|---|
| 46 |
if pkg_resources: |
|---|
| 47 |
parser.add_option('-R', '--requirement', |
|---|
| 48 |
help='Specify the default pkg_resources requirement for the ' |
|---|
| 49 |
'argument freeform resources. This option MUST be specified ' |
|---|
| 50 |
'if -r is set AND ANY of your arguments are not of the form ' |
|---|
| 51 |
'"requirement:resource".', |
|---|
| 52 |
default=None) |
|---|
| 53 |
parser.add_option('-r', '--resource-sources', action='store_true', |
|---|
| 54 |
help='Set to indicate the command line arguments are setuptools ' |
|---|
| 55 |
'pkg_resources resources. Default [false]', |
|---|
| 56 |
default=False) |
|---|
| 57 |
|
|---|
| 58 |
parser.add_option('-d','--input-data-file', |
|---|
| 59 |
default=None, |
|---|
| 60 |
help='Read input from file rather than stdin') |
|---|
| 61 |
parser.add_option('-I', '--interpreter-shell', |
|---|
| 62 |
action='store_true', |
|---|
| 63 |
default=False, |
|---|
| 64 |
help='a very basic shell') |
|---|
| 65 |
parser.add_option('-V','--verbose', action="store_true", |
|---|
| 66 |
default=False) |
|---|
| 67 |
|
|---|
| 68 |
def compile_tool(): |
|---|
| 69 |
parser = optparse.OptionParser( |
|---|
| 70 |
usage=sys.modules[__name__].__doc__) |
|---|
| 71 |
add_options_compile_tool(parser) |
|---|
| 72 |
options, names = parser.parse_args() |
|---|
| 73 |
input = sys.stdin |
|---|
| 74 |
if options.input_data_file: |
|---|
| 75 |
input = open(options.input_data_file) |
|---|
| 76 |
if pkg_resources and options.resource_sources: |
|---|
| 77 |
for n in names: |
|---|
| 78 |
n=n.split(':',1) |
|---|
| 79 |
if len(n)==2: |
|---|
| 80 |
requirement,resource = pkg_resources.Requirement(n[0]),n[1] |
|---|
| 81 |
else: |
|---|
| 82 |
if not options.requirement: |
|---|
| 83 |
print ('[ERROR] using pkg_resources arguments requires ' |
|---|
| 84 |
'you either specify -R defaultrequirement, OR ' |
|---|
| 85 |
'you format each of the arguments as ' |
|---|
| 86 |
'"requirement:resource".') |
|---|
| 87 |
raise SystemExit |
|---|
| 88 |
requirement,resource=pkg_resources.Requirement( |
|---|
| 89 |
options.requirement),n[0] |
|---|
| 90 |
resources.append((requirement, resource)) |
|---|
| 91 |
ft, e, s = compile_aggregate_resources(resources) |
|---|
| 92 |
else: |
|---|
| 93 |
ft, e, s = compile_aggregate_files(names) |
|---|
| 94 |
if e: |
|---|
| 95 |
pprint(e) |
|---|
| 96 |
|
|---|
| 97 |
formtable_prepare(ft) |
|---|
| 98 |
if options.verbose: |
|---|
| 99 |
pprint(ft) |
|---|
| 100 |
|
|---|
| 101 |
# prepare a banner decribing the forms we can match based on the supplied |
|---|
| 102 |
# sources. |
|---|
| 103 |
banner = ( |
|---|
| 104 |
"\nEnter input corresponding to any of the following forms:\n%s" |
|---|
| 105 |
"\n\ncompiled from sources:\n%s" |
|---|
| 106 |
% (' \n'.join(['%s: %s' % describe_form(ft, formid) |
|---|
| 107 |
for formid in range(0, len(ft['form2command']))]),s)) |
|---|
| 108 |
|
|---|
| 109 |
if options.interpreter_shell: |
|---|
| 110 |
run_shell(ft, banner, input) |
|---|
| 111 |
else: |
|---|
| 112 |
# read user input from file or stdin and print the match results. |
|---|
| 113 |
for line in input.readlines(): |
|---|
| 114 |
line=line.strip() |
|---|
| 115 |
match,details = match_command(ft,line.split()) |
|---|
| 116 |
print match_input(ft, line) |
|---|
| 117 |
|
|---|
| 118 |
def match_input(formtable, line): |
|---|
| 119 |
match,details = match_command(formtable,line.split()) |
|---|
| 120 |
if type(details)==type({}): |
|---|
| 121 |
_,form=match |
|---|
| 122 |
return '%s: %s' % tuple(describe_form(formtable, form, **details)) |
|---|
| 123 |
if match is None and not len(details): |
|---|
| 124 |
return "<*** no match ***> for:'%s'" % line |
|---|
| 125 |
return '\n'.join( |
|---|
| 126 |
["<*** ambiguouse match ***> for:'%s'" % line]+ |
|---|
| 127 |
['%s: ?= %s' % describe_form(formtable,formid) |
|---|
| 128 |
for formid in details]) |
|---|
| 129 |
|
|---|
| 130 |
def describe_form(formtable, formid, **valuemap): |
|---|
| 131 |
try: |
|---|
| 132 |
command = formtable['form2command'][formid] |
|---|
| 133 |
except IndexError: |
|---|
| 134 |
return 'unknown','' |
|---|
| 135 |
ftypes=formtable['form2fieldtypes'][formid] |
|---|
| 136 |
fnames=formtable['form2fieldnames'][formid] |
|---|
| 137 |
matchdesc = ' '.join(['%s.%s=%s' % ( |
|---|
| 138 |
repr_fieldtype_compact(t), n, |
|---|
| 139 |
(t == FIELDTYPE_KEYWORD and n or valuemap.get(n,'?')) |
|---|
| 140 |
) |
|---|
| 141 |
for t,n in zip(ftypes,fnames) if n]) |
|---|
| 142 |
return command, matchdesc |
|---|
| 143 |
|
|---|
| 144 |
def compile_aggregate_resources(resources, compiler=None): |
|---|
| 145 |
compiler = compiler or compile |
|---|
| 146 |
sources = [pkg_resources.resource_string(*resource) |
|---|
| 147 |
for resource in [ |
|---|
| 148 |
((not isinstance(req, pkg_resources.Requirement) and |
|---|
| 149 |
pkg_resources.Requirement.parse(req)) or req,res) |
|---|
| 150 |
for req,res in resources]] |
|---|
| 151 |
(c,f), e = compiler(sources) |
|---|
| 152 |
ft = create_formtable(c,f) |
|---|
| 153 |
return ft, e, ''.join(sources) |
|---|
| 154 |
|
|---|
| 155 |
def compile_aggregate_files(files, compiler=None): |
|---|
| 156 |
compiler = compiler or compile |
|---|
| 157 |
errors, sources = [],[] |
|---|
| 158 |
for f in files: |
|---|
| 159 |
try: |
|---|
| 160 |
sources.append(file(f,'r').read()) |
|---|
| 161 |
except IOError, e: |
|---|
| 162 |
errors.append(e) |
|---|
| 163 |
(c,f), e = compiler(sources) |
|---|
| 164 |
ft=create_formtable(c,f) |
|---|
| 165 |
return ft, e, ''.join(sources) |
|---|
| 166 |
|
|---|
| 167 |
def compile_commandset(sources, compiler=None): |
|---|
| 168 |
compiler = compiler or compile |
|---|
| 169 |
(c,f), e = compiler(sources) |
|---|
| 170 |
ft = create_formtable(c, f) |
|---|
| 171 |
return ft, e, ''.join(sources) |
|---|
| 172 |
|
|---|
| 173 |
def run_shell(formtable, banner, input, fshell=None): |
|---|
| 174 |
if not fshell: |
|---|
| 175 |
from cmd import Cmd |
|---|
| 176 |
class FreeformShell(Cmd): |
|---|
| 177 |
prompt='freeform:' |
|---|
| 178 |
def default(self, x): |
|---|
| 179 |
print x |
|---|
| 180 |
def precmd(self, line): |
|---|
| 181 |
matched = match_input(formtable, line) |
|---|
| 182 |
return matched |
|---|
| 183 |
fshell = FreeformShell(None, input) |
|---|
| 184 |
try: |
|---|
| 185 |
fshell.cmdloop(banner) |
|---|
| 186 |
except KeyboardInterrupt, e: |
|---|
| 187 |
raise SystemExit |
|---|
| 188 |
|
|---|
| 189 |
|
|---|
| 190 |
if __name__ == '__main__': |
|---|
| 191 |
from os import environ |
|---|
| 192 |
if environ.get('WINGDBSTUB', False): |
|---|
| 193 |
import wingdbstub |
|---|
| 194 |
compile_tool() |
|---|