diff --git a/VERSION b/VERSION index 5250e94b..9789059a 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -Version 2.6.0-development+timestamp.2013.08.07.09.02.12 +Version 2.6.0-development+timestamp.2013.08.07.18.02.33 diff --git a/gluon/shell.py b/gluon/shell.py index 92d59291..53cd5331 100644 --- a/gluon/shell.py +++ b/gluon/shell.py @@ -24,7 +24,7 @@ from utils import web2py_uuid from compileapp import build_environment, read_pyc, run_models_in from restricted import RestrictedError from globals import Request, Response, Session -from storage import Storage +from storage import Storage, List from admin import w2p_unpack from dal import BaseAdapter @@ -131,13 +131,21 @@ def env( request.function = f or 'index' response.view = '%s/%s.html' % (request.controller, request.function) - request.env.path_info = '/%s/%s/%s' % (a, c, f) request.env.http_host = '127.0.0.1:8000' request.env.remote_addr = '127.0.0.1' request.env.web2py_runtime_gae = global_settings.web2py_runtime_gae for k, v in extra_request.items(): request[k] = v + + path_info = '/%s/%s/%s' % (a, c, f) + if request.args: + path_info = '%s/%s' % (path_info, '/'.join(request.args)) + if request.vars: + vars = ['%s=%s' % (k,v) if v else '%s' % k + for (k,v) in request.vars.iteritems()] + path_info = '%s?%s' % (path_info, '&'.join(vars)) + request.env.path_info = path_info # Monkey patch so credentials checks pass. @@ -187,7 +195,7 @@ def run( a/c exec the controller c into the application environment """ - (a, c, f) = parse_path_info(appname) + (a, c, f, args, vars) = parse_path_info(appname, av=True) errmsg = 'invalid application name: %s' % appname if not a: die(errmsg) @@ -219,18 +227,23 @@ def run( if c: import_models = True - _env = env(a, c=c, f=f, import_models=import_models) + extra_request = {} + if args: + extra_request['args'] = args + if vars: + extra_request['vars'] = vars + _env = env(a, c=c, f=f, import_models=import_models, extra_request=extra_request) if c: - cfile = os.path.join('applications', a, 'controllers', c + '.py') - if not os.path.isfile(cfile): - cfile = os.path.join('applications', a, 'compiled', + pyfile = os.path.join('applications', a, 'controllers', c + '.py') + pycfile = os.path.join('applications', a, 'compiled', "controllers_%s_%s.pyc" % (c, f)) - if not os.path.isfile(cfile): - die(errmsg) - else: - exec read_pyc(cfile) in _env + if ((cronjob and os.path.isfile(pycfile)) + or not os.path.isfile(pyfile)): + exec read_pyc(pycfile) in _env + elif os.path.isfile(pyfile): + execfile(pyfile, _env) else: - execfile(cfile, _env) + die(errmsg) if f: exec ('print %s()' % f, _env) @@ -294,13 +307,25 @@ def run( code.interact(local=_env) -def parse_path_info(path_info): +def parse_path_info(path_info, av=False): """ Parse path info formatted like a/c/f where c and f are optional and a leading / accepted. Return tuple (a, c, f). If invalid path_info a is set to None. If c or f are omitted they are set to None. + If av=True, parse args and vars """ + if av: + vars = None + if '?' in path_info: + path_info, query = path_info.split('?', 2) + vars = Storage() + for var in query.split('&'): + (var, val) = var.split('=', 2) if '=' in var else (var, None) + vars[var] = val + items = List(path_info.split('/')) + args = List(items[3:]) if len(items) > 3 else None + return (items(0), items(1), items(2), args, vars) mo = re.match(r'^/?(?P\w+)(/(?P\w+)(/(?P\w+))?)?$', path_info) @@ -368,9 +393,10 @@ def test(testpath, import_models=True, verbose=False): globs = env(a, c=c, f=f, import_models=import_models) execfile(testfile, globs) - doctest.run_docstring_examples(obj, globs=globs, - name='%s: %s' % (os.path.basename(testfile), - name), verbose=verbose) + doctest.run_docstring_examples( + obj, globs=globs, + name='%s: %s' % (os.path.basename(testfile), + name), verbose=verbose) if type(obj) in (types.TypeType, types.ClassType): for attr_name in dir(obj): @@ -398,8 +424,8 @@ def execute_from_command_line(argv=None): parser = optparse.OptionParser(usage=get_usage()) parser.add_option('-S', '--shell', dest='shell', metavar='APPNAME', - help='run web2py in interactive shell or IPython(if installed) ' + - 'with specified appname') + help='run web2py in interactive shell ' + + 'or IPython(if installed) with specified appname') msg = 'run web2py in interactive shell or bpython (if installed) with' msg += ' specified appname (if app does not exist it will be created).' msg += '\n Use combined with --shell' diff --git a/gluon/widget.py b/gluon/widget.py index 6d63fb94..2ea47e77 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -63,11 +63,13 @@ def run_system_tests(options): if options.with_coverage: try: import coverage - coverage_config = os.environ.get("COVERAGE_PROCESS_START", - os.path.join('gluon', 'tests', 'coverage.ini') - ) - call_args = ['coverage', 'run', '--rcfile=%s' % coverage_config, - '-m', 'unittest', '-v', 'gluon.tests'] + coverage_config = os.environ.get( + "COVERAGE_PROCESS_START", + os.path.join('gluon', 'tests', 'coverage.ini')) + + call_args = ['coverage', 'run', '--rcfile=%s' % + coverage_config, + '-m', 'unittest', '-v', 'gluon.tests'] except: sys.stderr.write('Coverage was not installed, skipping\n') sys.stderr.write("Python 2.7\n") @@ -157,7 +159,8 @@ def presentation(root): # Prevent garbage collection of img pnl.image = img - def add_label(text='Change Me', font_size=12, foreground='#195866', height=1): + def add_label(text='Change Me', font_size=12, + foreground='#195866', height=1): return Tkinter.Label( master=canvas, width=250, @@ -331,11 +334,13 @@ class web2pyDialog(object): apps = [] available_apps = [arq for arq in os.listdir('applications/')] available_apps = [arq for arq in available_apps - if os.path.exists('applications/%s/models/scheduler.py' % arq)] + if os.path.exists( + 'applications/%s/models/scheduler.py' % arq)] if start: #the widget takes care of starting the scheduler if self.options.scheduler and self.options.with_scheduler: - apps = [app.strip() for app in self.options.scheduler.split(',') + apps = [app.strip() for app + in self.options.scheduler.split(',') if app in available_apps] for app in apps: self.try_start_scheduler(app) @@ -419,13 +424,14 @@ class web2pyDialog(object): """ Connect pages """ #reset the menu available_apps = [arq for arq in os.listdir('applications/') - if os.path.exists('applications/%s/__init__.py' % arq)] + if os.path.exists( + 'applications/%s/__init__.py' % arq)] self.pagesmenu.delete(0, len(available_apps)) for arq in available_apps: url = self.url + arq - self.pagesmenu.add_command(label=url, - command=lambda u=url: start_browser(u)) - + self.pagesmenu.add_command( + label=url, command=lambda u=url: start_browser(u)) + def quit(self, justHide=False): """ Finish the program execution """ if justHide: @@ -478,7 +484,8 @@ class web2pyDialog(object): return self.error('invalid port number') # Check for non default value for ssl inputs - if (len(self.options.ssl_certificate) > 0) or (len(self.options.ssl_private_key) > 0): + if (len(self.options.ssl_certificate) > 0 or + len(self.options.ssl_private_key) > 0): proto = 'https' else: proto = 'http' @@ -521,8 +528,8 @@ class web2pyDialog(object): self.button_stop.configure(state='normal') if not options.taskbar: - thread.start_new_thread(start_browser, - (get_url(ip, proto=proto, port=port), True)) + thread.start_new_thread( + start_browser, (get_url(ip, proto=proto, port=port), True)) self.password.configure(state='readonly') [ip.configure(state='disabled') for ip in self.ips.values()] @@ -1110,7 +1117,7 @@ def start(cron=True): if not options.args is None: sys.argv[:] = options.args run(options.shell, plain=options.plain, bpython=options.bpython, - import_models=options.import_models, startfile=options.run) + import_models=options.import_models, startfile=options.run, cronjob=options.cronjob) return # ## if -C start cron run (extcron) and exit