root/freeform/trunk/freeform/tool.py

Revision 229, 6.6 kB (checked in by robin, 2 years ago)

* compile_commandset: like the aggregate family of compile functions except

it just works with strings. for the benefit of people who dont put there
data in pkg_resources compatible python modules

* WINGDBSTUB environment variable

Line 
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()
Note: See TracBrowser for help on using the browser.