Browse Source

Code cleanup

subparsing
chriskiehl 10 years ago
parent
commit
2a71297a68
3 changed files with 100 additions and 76 deletions
  1. 3
      gooey/python_bindings/config_generator.py
  2. 76
      gooey/python_bindings/docopt_to_json.py
  3. 97
      gooey/python_bindings/gooey_decorator.py

3
gooey/python_bindings/config_generator.py

@ -20,7 +20,8 @@ def create_from_parser(parser, source_path, **kwargs):
'default_size': kwargs.get('default_size', (610, 530)),
'requireds_cols': kwargs.get('required_cols', 1),
'optionals_cols': kwargs.get('optional_cols', 3),
'manual_start': False
'manual_start': False,
'layout_type': 'column'
}
if show_config:

76
gooey/python_bindings/docopt_to_json.py

@ -0,0 +1,76 @@
"""
Naval Fate.
Usage:
naval_fate.py ship new <name>...
naval_fate.py ship <name> move <x> <y> [--speed=<kn>]
naval_fate.py ship shoot <x> <y>
naval_fate.py mine (set|remove) <x> <y> [--moored|--drifting]
naval_fate.py -h | --help
naval_fate.py --version
Options:
-h --help Show this screen.
--version Show version.
--speed=<kn> Speed in knots [default: 10].
--moored Moored (anchored) mine.
--drifting Drifting mine.
"""
# Standard
# choice
# counter
# flag
# mutually_exclusive
#
# types?
from docopt import docopt, Option, Argument
class MyOption(Option):
def __init__(self, *args, **kwargs):
self.description = kwargs.pop('description', None)
super(MyOption, self).__init__(*args, **kwargs)
@classmethod
def parse(class_, option_description):
short, long, argcount, value = None, None, 0, False
options, _, description = option_description.strip().partition(' ')
options = options.replace(',', ' ').replace('=', ' ')
for s in options.split():
if s.startswith('--'):
long = s
elif s.startswith('-'):
short = s
else:
argcount = 1
if argcount:
matched = re.findall('\[default: (.*)\]', description, flags=re.I)
value = matched[0] if matched else None
return class_(short, long, argcount, value, description=description.strip())
def __repr__(self):
return 'Option(%r, %r, %r, %r, %r)' % (self.short, self.long,
self.argcount, self.value, self.description)
if __name__ == '__main__':
import sys
a = docopt(__doc__)
# import re
# doc = __doc__
# split = re.split('\n *(<\S+?>|-\S+?)', doc)[1:]
# split = [s1 + s2 for s1, s2 in zip(split[::2], split[1::2])]
# options = [MyOption.parse(s) for s in split if s.startswith('-')]
# arguments = [Argument.parse(s) for s in split if s.startswith('<')]
# #return options, arguments
# print arguments
# print options
print a
a = 10

97
gooey/python_bindings/gooey_decorator.py

@ -3,88 +3,21 @@ Created on Jan 24, 2014
@author: Chris
Hey, whaduya know. This is out of date again. TODO: update giant doctring.
##How things work these days (though, likely to change)
The decorator is used solely as a nice way to get the location
of the executing script. It no longer returns a decorated version
of the client code, but in fact completely hijacks the execution.
So, rather than returning a reference to the client's main, it now
returns itself, thus short-circuiting the execution of the client
program.
What it DOES do now is grab where the client module is stored and
read it in as a file so that it can hack away at it.
The first step, as before, is getting the ArgumentParser reference
so that the needed values can be extracted. This is done by reading
the source file up to the point where the `parse_args()` method is
called. This puts us smack in the middle of the client's `main` method.
This first half guarantees that all imports, modules, variable assignments,
etc.. are caught (unlike before).
Next step: getting the rest of the source code that's relevant
The file is again read up to the `parse_args` call, but this time everything
leading up to that point is dropped and we keep only the remainder of the file.
So, now the top and the bottom is located, but the bottom needs to be trimmed a
little more -- we want to drop everything remaining in the main method.
So, we `dropwhile` lines are currently indented (and thus still part of the `main`
method)
Finally, we arrive at the end, which gives us an exact copy of the original source
file, minus all of it's main logic. The two pieces are then sandwiched together,
saved to a file, and imported as a new module. Now all that has to be done is call
it (moddified) main function, and bam! It returns to fully populated parser object
to us. No more complicated ast stuff. Just a little bit of string parsing and we're
done.
TODO: this
'''
from argparse import ArgumentParser
import json
import os
import sys
import json
import atexit
import tempfile
import source_parser
import config_generator
from gooey.gui import application
from gooey.gui.windows import layouts
from gooey.python_bindings import argparse_to_json
def decorator(func):
def graphical_parse_args(self, args=None, namespace=None):
values = [raw_input("Enter %s (%s):" % (a.dest, a.help)) for a in self._actions]
raw_input('Press enter to start')
# update new args with what you get from the graphical widgets
return self.original_parse_args(arg_lst, namespace)
def inner(*args, **kwargs):
ArgumentParser.original_parse_args = ArgumentParser.parse_args
ArgumentParser.parse_args = graphical_parse_args
return func(*args, **kwargs)
from . import source_parser
from . import config_generator
from gooey.gui import application
return inner
def store_executable_copy():
main_module_path = get_caller_path()
_, filename = os.path.split(main_module_path)
cleaned_source = clean_source(main_module_path)
descriptor, tmp_filepath = tempfile.mkstemp(suffix='.py')
atexit.register(cleanup, descriptor, tmp_filepath)
from argparse import ArgumentParser
with open(tmp_filepath, 'w') as f:
f.write(cleaned_source)
return tmp_filepath
def Gooey(f=None,
advanced=True,
@ -93,7 +26,7 @@ def Gooey(f=None,
program_name=None,
program_description=None,
default_size=(610, 530),
required_cols=3,
required_cols=2,
optional_cols=2,
dump_build_config=False):
'''
@ -111,7 +44,7 @@ def Gooey(f=None,
if dump_build_config:
config_path = os.path.join(os.getcwd(), 'gooey_config.json')
print 'Writing Build Config to: {}'.format(config_path)
print( 'Writing Build Config to: {}'.format(config_path))
with open(config_path, 'w') as f:
f.write(json.dumps(build_spec, indent=2))
@ -130,6 +63,19 @@ def Gooey(f=None,
return build
def store_executable_copy():
main_module_path = get_caller_path()
_, filename = os.path.split(main_module_path)
cleaned_source = clean_source(main_module_path)
descriptor, tmp_filepath = tempfile.mkstemp(suffix='.py')
atexit.register(cleanup, descriptor, tmp_filepath)
with open(tmp_filepath, 'w') as f:
f.write(cleaned_source)
return tmp_filepath
def clean_source(module_path):
with open(module_path, 'r') as f:
return ''.join(
@ -140,6 +86,7 @@ def clean_source(module_path):
def get_parser(module_path):
return source_parser.extract_parser(module_path)
def get_caller_path():
tmp_sys = __import__('sys')
return tmp_sys.argv[0]

Loading…
Cancel
Save