diff --git a/gluon/globals.py b/gluon/globals.py
index 44c9b794..fc14ceff 100644
--- a/gluon/globals.py
+++ b/gluon/globals.py
@@ -56,8 +56,6 @@ except ImportError:
have_minify = False
-regex_session_id = re.compile('^([\w\-]+/)?[\w\-\.]+$')
-
__all__ = ['Request', 'Response', 'Session']
current = threading.local() # thread-local storage for request-scope globals
@@ -357,9 +355,11 @@ class Request(Storage):
"""
cmd_opts = global_settings.cmd_options
# checking if this is called within the scheduler or within the shell
- # in addition to checking if it's not a cronjob
- if ((cmd_opts and (cmd_opts.shell or cmd_opts.scheduler))
- or global_settings.cronjob or self.is_https):
+ # in addition to checking if it's a cronjob
+ # FIXME: cmd_opts.scheduler does not imply that
+ # we are running in the scheduler
+ if (self.is_https or cmd_opts and (
+ cmd_opts.shell or cmd_opts.scheduler or cmd_opts.cronjob)):
current.session.secure()
else:
current.session.forget()
@@ -602,6 +602,7 @@ class Response(Storage):
# for attachment settings and backward compatibility
keys = [item.lower() for item in headers]
if attachment:
+ # FIXME: should be done like in next download method
if filename is None:
attname = ""
else:
@@ -654,6 +655,7 @@ class Response(Storage):
Downloads from http://..../download/filename
"""
+ from pydal.helpers.regex import REGEX_UPLOAD_PATTERN
from pydal.exceptions import NotAuthorizedException, NotFoundException
current.session.forget(current.response)
@@ -661,10 +663,10 @@ class Response(Storage):
if not request.args:
raise HTTP(404)
name = request.args[-1]
- items = re.compile('(?P
.*?)\.(?P.*?)\..*').match(name)
+ items = re.match(REGEX_UPLOAD_PATTERN, name)
if not items:
raise HTTP(404)
- (t, f) = (items.group('table'), items.group('field'))
+ t = items.group('table'); f = items.group('field')
try:
field = db[t][f]
except (AttributeError, KeyError):
@@ -801,6 +803,8 @@ class Session(Storage):
- session_filename
"""
+ REGEX_SESSION_FILE = r'^(?:[\w-]+/)?[\w.-]+$'
+
def connect(self,
request=None,
response=None,
@@ -891,7 +895,7 @@ class Session(Storage):
response.session_file = None
# check if the session_id points to a valid sesion filename
if response.session_id:
- if not regex_session_id.match(response.session_id):
+ if not re.match(self.REGEX_SESSION_FILE, response.session_id):
response.session_id = None
else:
response.session_filename = \
diff --git a/gluon/newcron.py b/gluon/newcron.py
index a415b530..5eba24e0 100644
--- a/gluon/newcron.py
+++ b/gluon/newcron.py
@@ -31,7 +31,6 @@ _cron_subprocs = []
def absolute_path_link(path):
"""
Returns an absolute path for the destination of a symlink
-
"""
if os.path.islink(path):
link = os.readlink(path)
@@ -73,16 +72,17 @@ class extcron(threading.Thread):
class hardcron(threading.Thread):
- def __init__(self, applications_parent):
+ def __init__(self, applications_parent, apps=None):
threading.Thread.__init__(self)
self.setDaemon(True)
self.path = applications_parent
- crondance(self.path, 'hard', startup=True)
+ self.apps = apps
+ crondance(self.path, 'hard', startup=True, apps=self.apps)
def launch(self):
if not _cron_stopping:
logger.debug('hard cron invocation')
- crondance(self.path, 'hard', startup=False)
+ crondance(self.path, 'hard', startup=False, apps=self.apps)
def run(self):
s = sched.scheduler(time.time, time.sleep)
@@ -95,15 +95,16 @@ class hardcron(threading.Thread):
class softcron(threading.Thread):
- def __init__(self, applications_parent):
+ def __init__(self, applications_parent, apps=None):
threading.Thread.__init__(self)
self.path = applications_parent
- # crondance(self.path, 'soft', startup=True)
+ self.apps = apps
+ # crondance(self.path, 'soft', startup=True, apps=self.apps)
def run(self):
if not _cron_stopping:
logger.debug('soft cron invocation')
- crondance(self.path, 'soft', startup=False)
+ crondance(self.path, 'soft', startup=False, apps=self.apps)
class Token(object):
@@ -270,7 +271,10 @@ class cronlauncher(threading.Thread):
def crondance(applications_parent, ctype='soft', startup=False, apps=None):
- # TODO: docstring
+ """
+ Does the periodic job of cron service: read the crontab(s) and launch
+ the various commands.
+ """
apppath = os.path.join(applications_parent, 'applications')
token = Token(applications_parent)
cronmaster = token.acquire(startup=startup)
@@ -299,7 +303,7 @@ def crondance(applications_parent, ctype='soft', startup=False, apps=None):
base_commands.append(w2p_path)
if applications_parent != global_settings.gluon_parent:
base_commands.extend(('-f', applications_parent))
- base_commands.extend(('-J',
+ base_commands.extend(('--cronjob', '--no-banner', '--nogui', '--plain',
# FIXME: this should not be needed since we are
# not launching the web server
'-a', '""'))
diff --git a/gluon/packages/dal b/gluon/packages/dal
index f3401dd8..f1cf5aab 160000
--- a/gluon/packages/dal
+++ b/gluon/packages/dal
@@ -1 +1 @@
-Subproject commit f3401dd8c05d089cb49cfd1215e2991388eace09
+Subproject commit f1cf5aab12b839ec168cc194f10c33e026b3de6b
diff --git a/gluon/widget.py b/gluon/widget.py
index 68e3b87a..bed5a665 100644
--- a/gluon/widget.py
+++ b/gluon/widget.py
@@ -216,6 +216,14 @@ class web2pyDialog(object):
self.bannerarea.after(1000, self.update_canvas)
# IP
+ # retrieves the list of server IP addresses
+ try:
+ if_ips = list(set( # no duplicates
+ [addrinfo[4][0] for addrinfo in getipaddrinfo(socket.getfqdn())
+ if not is_loopback_ip_address(addrinfo=addrinfo)]))
+ except socket.gaierror:
+ if_ips = []
+
tkinter.Label(self.root,
text='Server IP:', bg=bg_color,
justify=tkinter.RIGHT).grid(row=4,
@@ -226,7 +234,7 @@ class web2pyDialog(object):
row = 4
ips = [('127.0.0.1', 'Local (IPv4)')] + \
([('::1', 'Local (IPv6)')] if socket.has_ipv6 else []) + \
- [(ip, 'Public') for ip in options.ips] + \
+ [(ip, 'Public') for ip in if_ips] + \
[('0.0.0.0', 'Public')]
for ip, legend in ips:
self.ips[ip] = tkinter.Radiobutton(
@@ -704,7 +712,7 @@ web2py will attempt to run a GUI to ask for it when starting the web server
metavar='APPNAME', help=\
'run web2py in interactive shell or IPython (if installed) with ' \
'specified appname (if app does not exist it will be created). ' \
- 'APPNAME like a/c/f?x=y (c,f and vars x,y optional)')
+ 'APPNAME like a/c/f?x=y (c, f and vars optional)')
parser.add_option('-B', '--bpython',
default=False,
@@ -752,7 +760,7 @@ web2py will attempt to run a GUI to ask for it when starting the web server
default=None,
metavar='TEST_PATH', help=\
'run doctests in web2py environment; ' \
- 'TEST_PATH like a/c/f (c,f optional)')
+ 'TEST_PATH like a/c/f (c, f optional)')
parser.add_option('-C', '--cron', dest='extcron',
default=False,
@@ -777,7 +785,9 @@ web2py will attempt to run a GUI to ask for it when starting the web server
parser.add_option('-J', '--cronjob',
default=False,
action='store_true',
- help='identify cron-initiated command')
+ # NOTE: help suppressed because this option is
+ # intended for internal use only
+ help=optparse.SUPPRESS_HELP)
parser.add_option('-L', '--config',
default='',
@@ -840,6 +850,10 @@ web2py will attempt to run a GUI to ask for it when starting the web server
# TODO: warn or error if args (should be no unparsed arguments)
options.args = other_args
+ if options.taskbar and os.name != 'nt':
+ # TODO: warn and disable taskbar instead of exit
+ die('taskbar not supported on this platform')
+
if options.config.endswith('.py'):
options.config = options.config[:-3]
if options.config:
@@ -853,20 +867,6 @@ web2py will attempt to run a GUI to ask for it when starting the web server
if hasattr(options, key):
setattr(options, key, getattr(options2, key))
- # store in options.ips the list of server IP addresses
- try:
- options.ips = list(set( # no duplicates
- [addrinfo[4][0] for addrinfo in getipaddrinfo(socket.getfqdn())
- if not is_loopback_ip_address(addrinfo=addrinfo)]))
- except socket.gaierror:
- options.ips = []
-
- if options.cronjob:
- global_settings.cronjob = True # tell the world
- options.plain = True # cronjobs use a plain shell
- options.nobanner = True
- options.nogui = True
-
# transform options.interfaces, in the form
# "ip1:port1:key1:cert1:ca_cert1;[ip2]:port2;ip3:port3:key3:cert3"
# (no spaces; optional key:cert:ca_cert indicate SSL), into
@@ -1074,11 +1074,6 @@ def start(cron=True):
# if no password provided and have Tk library start GUI (when not
# explicitly disabled), we also need a GUI to put in taskbar (system tray)
# when requested
-
- # FIXME: this check should be done first
- if options.taskbar and os.name != 'nt':
- die('taskbar not supported on this platform')
-
root = None
if (not options.nogui and options.password == '') or options.taskbar: