Compare commits
6 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 4228b070d7 | |||
| c4e0ab2316 | |||
| ac6494387d | |||
| f6b9d20fd6 | |||
| 9d934e0e7b | |||
| a7963a2b0e |
+5
-1
@@ -12,7 +12,11 @@ python:
|
|||||||
- '2.7'
|
- '2.7'
|
||||||
- '3.6'
|
- '3.6'
|
||||||
- '3.7'
|
- '3.7'
|
||||||
- '3.8'
|
- 'pypy3.5'
|
||||||
|
|
||||||
|
matrix:
|
||||||
|
allow_failures:
|
||||||
|
- python: 'pypy3.5'
|
||||||
|
|
||||||
install:
|
install:
|
||||||
- pip install -e .
|
- pip install -e .
|
||||||
|
|||||||
@@ -1,7 +1,3 @@
|
|||||||
## 2.20.1
|
|
||||||
|
|
||||||
new makefile to update binaries from Nico Zanferrari
|
|
||||||
|
|
||||||
## 2.19.0
|
## 2.19.0
|
||||||
- new command line options (Thanks Paolo Pastori)
|
- new command line options (Thanks Paolo Pastori)
|
||||||
|
|
||||||
|
|||||||
@@ -45,7 +45,7 @@ rmfiles:
|
|||||||
rm -rf applications/examples/uploads/*
|
rm -rf applications/examples/uploads/*
|
||||||
src:
|
src:
|
||||||
### Use semantic versioning
|
### Use semantic versioning
|
||||||
echo 'Version 2.20.4-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
echo 'Version 2.18.5-stable+timestamp.'`date +%Y.%m.%d.%H.%M.%S` > VERSION
|
||||||
### rm -f all junk files
|
### rm -f all junk files
|
||||||
make clean
|
make clean
|
||||||
# make rmfiles
|
# make rmfiles
|
||||||
@@ -104,63 +104,6 @@ win:
|
|||||||
mv ../web2py_win/web2py/_ssl.pyd ../web2py_win/web2py/_ssl.pyd.legacy | echo 'done'
|
mv ../web2py_win/web2py/_ssl.pyd ../web2py_win/web2py/_ssl.pyd.legacy | echo 'done'
|
||||||
cd ../web2py_win; zip -r web2py_win.zip web2py
|
cd ../web2py_win; zip -r web2py_win.zip web2py
|
||||||
mv ../web2py_win/web2py_win.zip .
|
mv ../web2py_win/web2py_win.zip .
|
||||||
binaries:
|
|
||||||
echo '' > NEWINSTALL
|
|
||||||
cp VERSION ../web2py_win_py27/web2py/
|
|
||||||
cp README.markdown ../web2py_win_py27/web2py/
|
|
||||||
cp NEWINSTALL ../web2py_win_py27/web2py/
|
|
||||||
cp LICENSE ../web2py_win_py27/web2py/
|
|
||||||
cp CHANGELOG ../web2py_win_py27/web2py/
|
|
||||||
rm -rf ../web2py_win_py27/web2py/gluon
|
|
||||||
cp -r gluon ../web2py_win_py27/web2py/gluon
|
|
||||||
rm -rf ../web2py_win_py27/web2py/applications/*
|
|
||||||
cp -r applications/__init__.py ../web2py_win_py27/web2py/applications/
|
|
||||||
cp -r applications/admin ../web2py_win_py27/web2py/applications/
|
|
||||||
cp -r applications/welcome ../web2py_win_py27/web2py/applications/
|
|
||||||
cp -r applications/examples ../web2py_win_py27/web2py/applications/
|
|
||||||
cd ../web2py_win_py27; zip -r ../web2py/web2py_win_py27.zip web2py
|
|
||||||
|
|
||||||
cp VERSION ../web2py_win_py37/web2py/
|
|
||||||
cp README.markdown ../web2py_win_py37/web2py/
|
|
||||||
cp NEWINSTALL ../web2py_win_py37/web2py/
|
|
||||||
cp LICENSE ../web2py_win_py37/web2py/
|
|
||||||
cp CHANGELOG ../web2py_win_py37/web2py/
|
|
||||||
rm -rf ../web2py_win_py37/web2py/gluon
|
|
||||||
cp -r gluon ../web2py_win_py37/web2py/gluon
|
|
||||||
rm -rf ../web2py_win_py37/web2py/applications/*
|
|
||||||
cp -r applications/__init__.py ../web2py_win_py37/web2py/applications/
|
|
||||||
cp -r applications/admin ../web2py_win_py37/web2py/applications/
|
|
||||||
cp -r applications/welcome ../web2py_win_py37/web2py/applications/
|
|
||||||
cp -r applications/examples ../web2py_win_py37/web2py/applications/
|
|
||||||
cd ../web2py_win_py37; zip -r ../web2py/web2py_win_py37.zip web2py
|
|
||||||
|
|
||||||
cp VERSION ../web2py_osx_py27/web2py.app/Contents/MacOS/
|
|
||||||
cp README.markdown ../web2py_osx_py27/web2py.app/Contents/MacOS/
|
|
||||||
cp NEWINSTALL ../web2py_osx_py27/web2py.app/Contents/MacOS/
|
|
||||||
cp LICENSE ../web2py_osx_py27/web2py.app/Contents/MacOS/
|
|
||||||
cp CHANGELOG ../web2py_osx_py27/web2py.app/Contents/MacOS/
|
|
||||||
rm -rf ../web2py_osx_py27/web2py.app/Contents/MacOS/gluon
|
|
||||||
cp -r gluon ../web2py_osx_py27/web2py.app/Contents/MacOS/gluon
|
|
||||||
rm -rf ../web2py_osx_py27/web2py.app/Contents/MacOS/applications/*
|
|
||||||
cp -r applications/__init__.py ../web2py_osx_py27/web2py.app/Contents/MacOS/applications/
|
|
||||||
cp -r applications/admin ../web2py_osx_py27/web2py.app/Contents/MacOS/applications/
|
|
||||||
cp -r applications/welcome ../web2py_osx_py27/web2py.app/Contents/MacOS/applications/
|
|
||||||
cp -r applications/examples ../web2py_osx_py27/web2py.app/Contents/MacOS/applications/
|
|
||||||
cd ../web2py_osx_py27; zip -r ../web2py/web2py_osx_py27.zip web2py.app
|
|
||||||
|
|
||||||
cp VERSION ../web2py_osx_py37/web2py.app/Contents/MacOS/
|
|
||||||
cp README.markdown ../web2py_osx_py37/web2py.app/Contents/MacOS/
|
|
||||||
cp NEWINSTALL ../web2py_osx_py37/web2py.app/Contents/MacOS/
|
|
||||||
cp LICENSE ../web2py_osx_py37/web2py.app/Contents/MacOS/
|
|
||||||
cp CHANGELOG ../web2py_osx_py37/web2py.app/Contents/MacOS/
|
|
||||||
rm -rf ../web2py_osx_py37/web2py.app/Contents/MacOS/gluon
|
|
||||||
cp -r gluon ../web2py_osx_py37/web2py.app/Contents/MacOS/gluon
|
|
||||||
rm -rf ../web2py_osx_py37/web2py.app/Contents/MacOS/applications/*
|
|
||||||
cp -r applications/__init__.py ../web2py_osx_py37/web2py.app/Contents/MacOS/applications/
|
|
||||||
cp -r applications/admin ../web2py_osx_py37/web2py.app/Contents/MacOS/applications/
|
|
||||||
cp -r applications/welcome ../web2py_osx_py37/web2py.app/Contents/MacOS/applications/
|
|
||||||
cp -r applications/examples ../web2py_osx_py37/web2py.app/Contents/MacOS/applications/
|
|
||||||
cd ../web2py_osx_py37; zip -r ../web2py/web2py_osx_py37.zip web2py.app
|
|
||||||
run:
|
run:
|
||||||
python2.7 web2py.py -a hello
|
python2.7 web2py.py -a hello
|
||||||
commit:
|
commit:
|
||||||
|
|||||||
@@ -1 +1 @@
|
|||||||
Version 2.20.4-stable+timestamp.2020.05.02.22.03.36
|
Version 2.18.5-stable+timestamp.2019.04.07.21.13.59
|
||||||
|
|||||||
@@ -194,6 +194,8 @@ def select():
|
|||||||
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
||||||
match.group('table'), match.group('field'),
|
match.group('table'), match.group('field'),
|
||||||
match.group('value'))
|
match.group('value'))
|
||||||
|
else:
|
||||||
|
request.vars.query = session.last_query
|
||||||
query = get_query(request)
|
query = get_query(request)
|
||||||
if request.vars.start:
|
if request.vars.start:
|
||||||
start = int(request.vars.start)
|
start = int(request.vars.start)
|
||||||
@@ -220,6 +222,7 @@ def select():
|
|||||||
else:
|
else:
|
||||||
orderby = '~' + orderby
|
orderby = '~' + orderby
|
||||||
session.last_orderby = orderby
|
session.last_orderby = orderby
|
||||||
|
session.last_query = request.vars.query
|
||||||
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
||||||
_name='query', _value=request.vars.query or '', _class='form-control',
|
_name='query', _value=request.vars.query or '', _class='form-control',
|
||||||
requires=IS_NOT_EMPTY(
|
requires=IS_NOT_EMPTY(
|
||||||
|
|||||||
@@ -1261,7 +1261,7 @@ def plugin():
|
|||||||
defines = {}
|
defines = {}
|
||||||
for m in models:
|
for m in models:
|
||||||
data = safe_read(apath('%s/models/%s' % (app, m), r=request))
|
data = safe_read(apath('%s/models/%s' % (app, m), r=request))
|
||||||
defines[m] = re.findall(REGEX_DEFINE_TABLE, data, re.MULTILINE)
|
defines[m] = regex_tables.findall(data)
|
||||||
defines[m].sort()
|
defines[m].sort()
|
||||||
|
|
||||||
# Get all controllers
|
# Get all controllers
|
||||||
|
|||||||
@@ -6,10 +6,7 @@ from gluon.fileutils import read_file
|
|||||||
from gluon.utils import web2py_uuid
|
from gluon.utils import web2py_uuid
|
||||||
from pydal.contrib import portalocker
|
from pydal.contrib import portalocker
|
||||||
# ###########################################################
|
# ###########################################################
|
||||||
# ## make sure administrator is on localhost or https,
|
# ## make sure administrator is on localhost or https
|
||||||
# ## or from
|
|
||||||
# ## gluon.settings.global_settings.trusted_lan_prefix
|
|
||||||
# ## subnet
|
|
||||||
# ###########################################################
|
# ###########################################################
|
||||||
|
|
||||||
|
|
||||||
@@ -25,9 +22,6 @@ else:
|
|||||||
|
|
||||||
if request.is_https:
|
if request.is_https:
|
||||||
session.secure()
|
session.secure()
|
||||||
elif request.env.trusted_lan_prefix and \
|
|
||||||
request.client.startswith(request.env.trusted_lan_prefix):
|
|
||||||
request.is_local = True
|
|
||||||
elif not request.is_local and not DEMO_MODE:
|
elif not request.is_local and not DEMO_MODE:
|
||||||
raise HTTP(200, T('Admin is disabled because insecure channel'))
|
raise HTTP(200, T('Admin is disabled because insecure channel'))
|
||||||
|
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
<div style="overflow:auto; width:80%;">
|
<div style="overflow:auto; width:80%;">
|
||||||
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
||||||
{{upload=URL('download',args=request.args[0])}}
|
{{upload=URL('download',args=request.args[0])}}
|
||||||
{{=SQLTABLE(rows,linkto,upload,orderby=True,query=query,_class='table table-striped table-bordered sortable')}}
|
{{=SQLTABLE(rows,linkto,upload,orderby=True,_class='table table-striped table-bordered sortable')}}
|
||||||
</div>
|
</div>
|
||||||
{{pass}}
|
{{pass}}
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|||||||
@@ -194,6 +194,8 @@ def select():
|
|||||||
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
||||||
match.group('table'), match.group('field'),
|
match.group('table'), match.group('field'),
|
||||||
match.group('value'))
|
match.group('value'))
|
||||||
|
else:
|
||||||
|
request.vars.query = session.last_query
|
||||||
query = get_query(request)
|
query = get_query(request)
|
||||||
if request.vars.start:
|
if request.vars.start:
|
||||||
start = int(request.vars.start)
|
start = int(request.vars.start)
|
||||||
@@ -220,6 +222,7 @@ def select():
|
|||||||
else:
|
else:
|
||||||
orderby = '~' + orderby
|
orderby = '~' + orderby
|
||||||
session.last_orderby = orderby
|
session.last_orderby = orderby
|
||||||
|
session.last_query = request.vars.query
|
||||||
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
||||||
_name='query', _value=request.vars.query or '', _class='form-control',
|
_name='query', _value=request.vars.query or '', _class='form-control',
|
||||||
requires=IS_NOT_EMPTY(
|
requires=IS_NOT_EMPTY(
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
<div style="overflow:auto; width:80%;">
|
<div style="overflow:auto; width:80%;">
|
||||||
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
||||||
{{upload=URL('download',args=request.args[0])}}
|
{{upload=URL('download',args=request.args[0])}}
|
||||||
{{=SQLTABLE(rows,linkto,upload,orderby=True,query=query,_class='table table-striped table-bordered sortable')}}
|
{{=SQLTABLE(rows,linkto,upload,orderby=True,_class='table table-striped table-bordered sortable')}}
|
||||||
</div>
|
</div>
|
||||||
{{pass}}
|
{{pass}}
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|||||||
@@ -9,8 +9,8 @@
|
|||||||
<table class="twothirds">
|
<table class="twothirds">
|
||||||
<thead>
|
<thead>
|
||||||
<tr>
|
<tr>
|
||||||
<th>For Python 3.7</th>
|
<th>For Normal Users (Py3)</th>
|
||||||
<th>For Python 2.7</th>
|
<th>For Legacy Users (Py2)</th>
|
||||||
<th>For Testers</th>
|
<th>For Testers</th>
|
||||||
<th>For Developers</th>
|
<th>For Developers</th>
|
||||||
</tr>
|
</tr>
|
||||||
@@ -18,13 +18,13 @@
|
|||||||
<tbody>
|
<tbody>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_win_py37.zip">Windows binaries</a>
|
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_win.zip">Windows binaries</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_win_py27.zip">Windows binaries</a>
|
<a class="btn btn180 rounded" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_win_py2.zip">Windows binaries</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_win_py27.zip">Windows binaries</a>
|
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_win.zip">Windows binaries</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded red" href="http://github.com/web2py/web2py/">Git Repository</a>
|
<a class="btn btn180 rounded red" href="http://github.com/web2py/web2py/">Git Repository</a>
|
||||||
@@ -32,13 +32,13 @@
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_osx_py37.zip">Mac binaries</a>
|
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_osx.zip">Mac binaries</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_osx_py27.zip">Mac binaries</a>
|
<a class="btn btn180 rounded" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_osx_py2.zip">Mac binaries</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_osx_py37.zip">Mac binaries</a>
|
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_osx.zip">Mac binaries</a>
|
||||||
</td>
|
</td>
|
||||||
<td>
|
<td>
|
||||||
<a class="btn btn180 rounded" href="http://mdipierro.github.io/web2py/web2py_manual_5th.pdf">Manual</a>
|
<a class="btn btn180 rounded" href="http://mdipierro.github.io/web2py/web2py_manual_5th.pdf">Manual</a>
|
||||||
|
|||||||
@@ -30,9 +30,6 @@ except:
|
|||||||
|
|
||||||
if request.is_https:
|
if request.is_https:
|
||||||
session.secure()
|
session.secure()
|
||||||
elif request.env.trusted_lan_prefix and \
|
|
||||||
remote_addr.startswith(request.env.trusted_lan_prefix):
|
|
||||||
request.is_local = True
|
|
||||||
elif (remote_addr not in hosts) and (remote_addr != '127.0.0.1') and \
|
elif (remote_addr not in hosts) and (remote_addr != '127.0.0.1') and \
|
||||||
(request.function != 'manage'):
|
(request.function != 'manage'):
|
||||||
raise HTTP(200, T('appadmin is disabled because insecure channel'))
|
raise HTTP(200, T('appadmin is disabled because insecure channel'))
|
||||||
@@ -197,6 +194,8 @@ def select():
|
|||||||
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
request.vars.query = '%s.%s.%s==%s' % (request.args[0],
|
||||||
match.group('table'), match.group('field'),
|
match.group('table'), match.group('field'),
|
||||||
match.group('value'))
|
match.group('value'))
|
||||||
|
else:
|
||||||
|
request.vars.query = session.last_query
|
||||||
query = get_query(request)
|
query = get_query(request)
|
||||||
if request.vars.start:
|
if request.vars.start:
|
||||||
start = int(request.vars.start)
|
start = int(request.vars.start)
|
||||||
@@ -223,6 +222,7 @@ def select():
|
|||||||
else:
|
else:
|
||||||
orderby = '~' + orderby
|
orderby = '~' + orderby
|
||||||
session.last_orderby = orderby
|
session.last_orderby = orderby
|
||||||
|
session.last_query = request.vars.query
|
||||||
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
form = FORM(TABLE(TR(T('Query:'), '', INPUT(_style='width:400px',
|
||||||
_name='query', _value=request.vars.query or '', _class='form-control',
|
_name='query', _value=request.vars.query or '', _class='form-control',
|
||||||
requires=IS_NOT_EMPTY(
|
requires=IS_NOT_EMPTY(
|
||||||
|
|||||||
@@ -82,7 +82,7 @@
|
|||||||
<div style="overflow:auto; width:80%;">
|
<div style="overflow:auto; width:80%;">
|
||||||
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
{{linkto = lambda f, t, r: URL('update', args=[request.args[0], r, f]) if f else "#"}}
|
||||||
{{upload=URL('download',args=request.args[0])}}
|
{{upload=URL('download',args=request.args[0])}}
|
||||||
{{=SQLTABLE(rows,linkto,upload,orderby=True,query=query,_class='table table-striped table-bordered sortable')}}
|
{{=SQLTABLE(rows,linkto,upload,orderby=True,_class='table table-striped table-bordered sortable')}}
|
||||||
</div>
|
</div>
|
||||||
{{pass}}
|
{{pass}}
|
||||||
<br/><br/>
|
<br/><br/>
|
||||||
|
|||||||
@@ -10,6 +10,10 @@ environment:
|
|||||||
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
||||||
PYTHON_ARCH: "64"
|
PYTHON_ARCH: "64"
|
||||||
|
|
||||||
|
- PYTHON: "C:/Python35"
|
||||||
|
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
||||||
|
PYTHON_ARCH: "64"
|
||||||
|
|
||||||
- PYTHON: "C:/Python36"
|
- PYTHON: "C:/Python36"
|
||||||
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
COVERAGE_PROCESS_START: gluon/tests/coverage.ini
|
||||||
PYTHON_ARCH: "64"
|
PYTHON_ARCH: "64"
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ a = Analysis(['web2py.py'],
|
|||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
binaries=[('/System/Library/Frameworks/Tk.framework/Tk', 'tk'), ('/System/Library/Frameworks/Tcl.framework/Tcl', 'tcl')],
|
binaries=[('/System/Library/Frameworks/Tk.framework/Tk', 'tk'), ('/System/Library/Frameworks/Tcl.framework/Tcl', 'tcl')],
|
||||||
datas=[],
|
datas=[],
|
||||||
hiddenimports=['site-packages', 'argparse', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
hiddenimports=['site-packages', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
||||||
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'cProfile', 'csv', 'ctypes.wintypes',
|
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'cProfile', 'csv', 'ctypes.wintypes',
|
||||||
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
||||||
'ipaddress', 'imaplib', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
'ipaddress', 'imaplib', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ a = Analysis(['web2py.py'],
|
|||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[],
|
||||||
hiddenimports=['site-packages', 'argparse', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
hiddenimports=['site-packages', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
||||||
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'csv', 'ctypes.wintypes',
|
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'csv', 'ctypes.wintypes',
|
||||||
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
||||||
'ipaddress', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
'ipaddress', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ a = Analysis(['web2py.py'],
|
|||||||
pathex=['.'],
|
pathex=['.'],
|
||||||
binaries=[],
|
binaries=[],
|
||||||
datas=[],
|
datas=[],
|
||||||
hiddenimports=['site-packages', 'argparse', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
hiddenimports=['site-packages', 'cgi', 'cgitb', 'code', 'concurrent', 'concurrent.futures',
|
||||||
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'csv', 'ctypes.wintypes',
|
'concurrent.futures._base', 'concurrent.futures.process', 'concurrent.futures.thread', 'configparser', 'csv', 'ctypes.wintypes',
|
||||||
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
'email.mime', 'email.mime.base', 'email.mime.multipart', 'email.mime.nonmultipart', 'email.mime.text', 'html.parser', 'http.cookies',
|
||||||
'ipaddress', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
'ipaddress', 'imp', 'json', 'json.decoder', 'json.encoder', 'json.scanner', 'logging.config', 'logging.handlers', 'profile', 'pstats',
|
||||||
|
|||||||
@@ -44,18 +44,16 @@ See the documentation for WSGIServer/Server for more information.
|
|||||||
On most platforms, fcgi will fallback to regular CGI behavior if run in a
|
On most platforms, fcgi will fallback to regular CGI behavior if run in a
|
||||||
non-FastCGI context. If you want to force CGI behavior, set the environment
|
non-FastCGI context. If you want to force CGI behavior, set the environment
|
||||||
variable FCGI_FORCE_CGI to "Y" or "y".
|
variable FCGI_FORCE_CGI to "Y" or "y".
|
||||||
|
|
||||||
Modified for web2py
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__author__ = 'Allan Saddi <allan@saddi.com>'
|
__author__ = 'Allan Saddi <allan@saddi.com>'
|
||||||
__version__ = '$Revision$'
|
__version__ = '$Revision$'
|
||||||
|
|
||||||
import cgi
|
|
||||||
import sys
|
import sys
|
||||||
import os
|
import os
|
||||||
import signal
|
import signal
|
||||||
import struct
|
import struct
|
||||||
|
import cStringIO as StringIO
|
||||||
import select
|
import select
|
||||||
import socket
|
import socket
|
||||||
import errno
|
import errno
|
||||||
@@ -70,15 +68,6 @@ except ImportError:
|
|||||||
import dummy_threading as threading
|
import dummy_threading as threading
|
||||||
thread_available = False
|
thread_available = False
|
||||||
|
|
||||||
is_py2 = sys.version_info[0] == 2
|
|
||||||
|
|
||||||
if is_py2:
|
|
||||||
from cgi import escape
|
|
||||||
import cStringIO as StringIO
|
|
||||||
else:
|
|
||||||
from io import StringIO
|
|
||||||
from html import escape
|
|
||||||
|
|
||||||
# Apparently 2.3 doesn't define SHUT_WR? Assume it is 1 in this case.
|
# Apparently 2.3 doesn't define SHUT_WR? Assume it is 1 in this case.
|
||||||
if not hasattr(socket, 'SHUT_WR'):
|
if not hasattr(socket, 'SHUT_WR'):
|
||||||
socket.SHUT_WR = 1
|
socket.SHUT_WR = 1
|
||||||
@@ -245,9 +234,11 @@ class InputStream(object):
|
|||||||
total += len(line)
|
total += len(line)
|
||||||
if 0 < sizehint <= total:
|
if 0 < sizehint <= total:
|
||||||
break
|
break
|
||||||
yield self.readline()
|
line = self.readline()
|
||||||
|
return lines
|
||||||
|
|
||||||
__iter__ = readlines
|
def __iter__(self):
|
||||||
|
return self
|
||||||
|
|
||||||
def next(self):
|
def next(self):
|
||||||
r = self.readline()
|
r = self.readline()
|
||||||
@@ -445,13 +436,13 @@ def encode_pair(name, value):
|
|||||||
if nameLength < 128:
|
if nameLength < 128:
|
||||||
s = chr(nameLength)
|
s = chr(nameLength)
|
||||||
else:
|
else:
|
||||||
s = struct.pack('!L', nameLength | 0x80000000)
|
s = struct.pack('!L', nameLength | 0x80000000L)
|
||||||
|
|
||||||
valueLength = len(value)
|
valueLength = len(value)
|
||||||
if valueLength < 128:
|
if valueLength < 128:
|
||||||
s += chr(valueLength)
|
s += chr(valueLength)
|
||||||
else:
|
else:
|
||||||
s += struct.pack('!L', valueLength | 0x80000000)
|
s += struct.pack('!L', valueLength | 0x80000000L)
|
||||||
|
|
||||||
return s + name + value
|
return s + name + value
|
||||||
|
|
||||||
@@ -601,7 +592,7 @@ class Request(object):
|
|||||||
self._flush()
|
self._flush()
|
||||||
self._end(appStatus, protocolStatus)
|
self._end(appStatus, protocolStatus)
|
||||||
|
|
||||||
def _end(self, appStatus=0, protocolStatus=FCGI_REQUEST_COMPLETE):
|
def _end(self, appStatus=0L, protocolStatus=FCGI_REQUEST_COMPLETE):
|
||||||
self._conn.end_request(self, appStatus, protocolStatus)
|
self._conn.end_request(self, appStatus, protocolStatus)
|
||||||
|
|
||||||
def _flush(self):
|
def _flush(self):
|
||||||
@@ -624,7 +615,7 @@ class CGIRequest(Request):
|
|||||||
self.stderr = sys.stderr
|
self.stderr = sys.stderr
|
||||||
self.data = StringIO.StringIO()
|
self.data = StringIO.StringIO()
|
||||||
|
|
||||||
def _end(self, appStatus=0, protocolStatus=FCGI_REQUEST_COMPLETE):
|
def _end(self, appStatus=0L, protocolStatus=FCGI_REQUEST_COMPLETE):
|
||||||
sys.exit(appStatus)
|
sys.exit(appStatus)
|
||||||
|
|
||||||
def _flush(self):
|
def _flush(self):
|
||||||
@@ -673,7 +664,7 @@ class Connection(object):
|
|||||||
self.process_input()
|
self.process_input()
|
||||||
except EOFError:
|
except EOFError:
|
||||||
break
|
break
|
||||||
except (select.error, socket.error) as e:
|
except (select.error, socket.error), e:
|
||||||
if e.errno == errno.EBADF: # Socket was closed by Request.
|
if e.errno == errno.EBADF: # Socket was closed by Request.
|
||||||
break
|
break
|
||||||
raise
|
raise
|
||||||
@@ -723,7 +714,7 @@ class Connection(object):
|
|||||||
"""
|
"""
|
||||||
rec.write(self._sock)
|
rec.write(self._sock)
|
||||||
|
|
||||||
def end_request(self, req, appStatus=0,
|
def end_request(self, req, appStatus=0L,
|
||||||
protocolStatus=FCGI_REQUEST_COMPLETE, remove=True):
|
protocolStatus=FCGI_REQUEST_COMPLETE, remove=True):
|
||||||
"""
|
"""
|
||||||
End a Request.
|
End a Request.
|
||||||
@@ -772,7 +763,7 @@ class Connection(object):
|
|||||||
|
|
||||||
if not self._multiplexed and self._requests:
|
if not self._multiplexed and self._requests:
|
||||||
# Can't multiplex requests.
|
# Can't multiplex requests.
|
||||||
self.end_request(req, 0, FCGI_CANT_MPX_CONN, remove=False)
|
self.end_request(req, 0L, FCGI_CANT_MPX_CONN, remove=False)
|
||||||
else:
|
else:
|
||||||
self._requests[inrec.requestId] = req
|
self._requests[inrec.requestId] = req
|
||||||
|
|
||||||
@@ -863,7 +854,7 @@ class MultiplexedConnection(Connection):
|
|||||||
finally:
|
finally:
|
||||||
self._lock.release()
|
self._lock.release()
|
||||||
|
|
||||||
def end_request(self, req, appStatus=0,
|
def end_request(self, req, appStatus=0L,
|
||||||
protocolStatus=FCGI_REQUEST_COMPLETE, remove=True):
|
protocolStatus=FCGI_REQUEST_COMPLETE, remove=True):
|
||||||
self._lock.acquire()
|
self._lock.acquire()
|
||||||
try:
|
try:
|
||||||
@@ -958,7 +949,8 @@ class Server(object):
|
|||||||
this keyword is ignored; it's not possible to multiplex requests
|
this keyword is ignored; it's not possible to multiplex requests
|
||||||
at all.
|
at all.
|
||||||
"""
|
"""
|
||||||
self.handler = handler or self.default_handler
|
if handler is not None:
|
||||||
|
self.handler = handler
|
||||||
self.maxwrite = maxwrite
|
self.maxwrite = maxwrite
|
||||||
if thread_available:
|
if thread_available:
|
||||||
try:
|
try:
|
||||||
@@ -1085,7 +1077,7 @@ class Server(object):
|
|||||||
while self._keepGoing:
|
while self._keepGoing:
|
||||||
try:
|
try:
|
||||||
r, w, e = select.select([sock], [], [], timeout)
|
r, w, e = select.select([sock], [], [], timeout)
|
||||||
except select.error as e:
|
except select.error, e:
|
||||||
if e.errno == errno.EINTR:
|
if e.errno == errno.EINTR:
|
||||||
continue
|
continue
|
||||||
raise
|
raise
|
||||||
@@ -1133,13 +1125,13 @@ class Server(object):
|
|||||||
self._keepGoing = False
|
self._keepGoing = False
|
||||||
self._hupReceived = reload
|
self._hupReceived = reload
|
||||||
|
|
||||||
def default_handler(self, req):
|
def handler(self, req):
|
||||||
"""
|
"""
|
||||||
Default handler, which just raises an exception. Unless a handler
|
Default handler, which just raises an exception. Unless a handler
|
||||||
is passed at initialization time, this must be implemented by
|
is passed at initialization time, this must be implemented by
|
||||||
a subclass.
|
a subclass.
|
||||||
"""
|
"""
|
||||||
raise NotImplementedError(self.__class__.__name__ + '.handler')
|
raise NotImplementedError, self.__class__.__name__ + '.handler'
|
||||||
|
|
||||||
def error(self, req):
|
def error(self, req):
|
||||||
"""
|
"""
|
||||||
@@ -1155,7 +1147,8 @@ class WSGIServer(Server):
|
|||||||
FastCGI server that supports the Web Server Gateway Interface. See
|
FastCGI server that supports the Web Server Gateway Interface. See
|
||||||
<http://www.python.org/peps/pep-0333.html>.
|
<http://www.python.org/peps/pep-0333.html>.
|
||||||
"""
|
"""
|
||||||
def __init__(self, application, environ=None, multithreaded=True, **kw):
|
def __init__(self, application, environ=None,
|
||||||
|
multithreaded=True, **kw):
|
||||||
"""
|
"""
|
||||||
environ, if present, must be a dictionary-like object. Its
|
environ, if present, must be a dictionary-like object. Its
|
||||||
contents will be copied into application's environ. Useful
|
contents will be copied into application's environ. Useful
|
||||||
@@ -1163,7 +1156,7 @@ class WSGIServer(Server):
|
|||||||
|
|
||||||
Set multithreaded to False if your application is not MT-safe.
|
Set multithreaded to False if your application is not MT-safe.
|
||||||
"""
|
"""
|
||||||
if 'handler'in kw:
|
if kw.has_key('handler'):
|
||||||
del kw['handler'] # Doesn't make sense to let this through
|
del kw['handler'] # Doesn't make sense to let this through
|
||||||
super(WSGIServer, self).__init__(**kw)
|
super(WSGIServer, self).__init__(**kw)
|
||||||
|
|
||||||
@@ -1177,7 +1170,7 @@ class WSGIServer(Server):
|
|||||||
# Used to force single-threadedness
|
# Used to force single-threadedness
|
||||||
self._app_lock = thread.allocate_lock()
|
self._app_lock = thread.allocate_lock()
|
||||||
|
|
||||||
def default_handler(self, req):
|
def handler(self, req):
|
||||||
"""Special handler for WSGI."""
|
"""Special handler for WSGI."""
|
||||||
if req.role != FCGI_RESPONDER:
|
if req.role != FCGI_RESPONDER:
|
||||||
return FCGI_UNKNOWN_ROLE, 0
|
return FCGI_UNKNOWN_ROLE, 0
|
||||||
@@ -1247,7 +1240,7 @@ class WSGIServer(Server):
|
|||||||
try:
|
try:
|
||||||
if headers_sent:
|
if headers_sent:
|
||||||
# Re-raise if too late
|
# Re-raise if too late
|
||||||
raise exc_info[0](exc_info[1], exc_info[2])
|
raise exc_info[0], exc_info[1], exc_info[2]
|
||||||
finally:
|
finally:
|
||||||
exc_info = None # avoid dangling circular ref
|
exc_info = None # avoid dangling circular ref
|
||||||
else:
|
else:
|
||||||
@@ -1311,6 +1304,7 @@ class WSGIServer(Server):
|
|||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
def test_app(environ, start_response):
|
def test_app(environ, start_response):
|
||||||
"""Probably not the most efficient example."""
|
"""Probably not the most efficient example."""
|
||||||
|
import cgi
|
||||||
start_response('200 OK', [('Content-Type', 'text/html')])
|
start_response('200 OK', [('Content-Type', 'text/html')])
|
||||||
yield '<html><head><title>Hello World!</title></head>\n' \
|
yield '<html><head><title>Hello World!</title></head>\n' \
|
||||||
'<body>\n' \
|
'<body>\n' \
|
||||||
@@ -1319,10 +1313,10 @@ if __name__ == '__main__':
|
|||||||
names = environ.keys()
|
names = environ.keys()
|
||||||
names.sort()
|
names.sort()
|
||||||
for name in names:
|
for name in names:
|
||||||
yield '<tr><td>%s</td><td>%s</td></tr>\n' % (name, escape(environ[name]))
|
yield '<tr><td>%s</td><td>%s</td></tr>\n' % (
|
||||||
|
name, cgi.escape(`environ[name]`))
|
||||||
|
|
||||||
form = cgi.FieldStorage(fp=environ['wsgi.input'],
|
form = cgi.FieldStorage(fp=environ['wsgi.input'], environ=environ,
|
||||||
environ=environ,
|
|
||||||
keep_blank_values=1)
|
keep_blank_values=1)
|
||||||
if form.list:
|
if form.list:
|
||||||
yield '<tr><th colspan="2">Form data</th></tr>'
|
yield '<tr><th colspan="2">Form data</th></tr>'
|
||||||
|
|||||||
@@ -109,7 +109,7 @@ def saml2_handler(session, request, config_filename = None, entityid = None):
|
|||||||
client = Saml2Client(config_file = config_filename)
|
client = Saml2Client(config_file = config_filename)
|
||||||
if not entityid:
|
if not entityid:
|
||||||
idps = client.metadata.with_descriptor("idpsso")
|
idps = client.metadata.with_descriptor("idpsso")
|
||||||
entityid = list(idps.keys())[0]
|
entityid = idps.keys()[0]
|
||||||
bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]
|
bindings = [BINDING_HTTP_REDIRECT, BINDING_HTTP_POST]
|
||||||
binding, destination = client.pick_binding(
|
binding, destination = client.pick_binding(
|
||||||
"single_sign_on_service", bindings, "idpsso", entity_id=entityid)
|
"single_sign_on_service", bindings, "idpsso", entity_id=entityid)
|
||||||
|
|||||||
@@ -15,11 +15,7 @@
|
|||||||
|
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
import sys
|
import sys
|
||||||
|
if sys.version > '3':
|
||||||
if sys.version_info[0] < 3:
|
|
||||||
is_py2 = True
|
|
||||||
else:
|
|
||||||
is_py2 = False
|
|
||||||
unicode = str
|
unicode = str
|
||||||
|
|
||||||
|
|
||||||
@@ -164,8 +160,7 @@ class SoapDispatcher(object):
|
|||||||
# Now we change 'external' and 'model' to the received forms i.e. 'ext' and 'mod'
|
# Now we change 'external' and 'model' to the received forms i.e. 'ext' and 'mod'
|
||||||
# After that we know how the client has prefixed additional namespaces
|
# After that we know how the client has prefixed additional namespaces
|
||||||
|
|
||||||
decoded_xml = xml if is_py2 else xml.decode('utf8')
|
ns = NS_RX.findall(xml)
|
||||||
ns = NS_RX.findall(decoded_xml)
|
|
||||||
for k, v in ns:
|
for k, v in ns:
|
||||||
if v in self.namespaces.values():
|
if v in self.namespaces.values():
|
||||||
_ns_reversed[v] = k
|
_ns_reversed[v] = k
|
||||||
@@ -374,23 +369,23 @@ class SoapDispatcher(object):
|
|||||||
e['name'] = k
|
e['name'] = k
|
||||||
if array:
|
if array:
|
||||||
e[:] = {'minOccurs': "0", 'maxOccurs': "unbounded"}
|
e[:] = {'minOccurs': "0", 'maxOccurs': "unbounded"}
|
||||||
if v is None:
|
if v in TYPE_MAP.keys():
|
||||||
|
t = 'xsd:%s' % TYPE_MAP[v]
|
||||||
|
elif v is None:
|
||||||
t = 'xsd:anyType'
|
t = 'xsd:anyType'
|
||||||
elif type(v) == list:
|
elif isinstance(v, list):
|
||||||
n = "ArrayOf%s%s" % (name, k)
|
n = "ArrayOf%s%s" % (name, k)
|
||||||
l = []
|
l = []
|
||||||
for d in v:
|
for d in v:
|
||||||
l.extend(d.items())
|
l.extend(d.items())
|
||||||
parse_element(n, l, array=True, complex=True)
|
parse_element(n, l, array=True, complex=True)
|
||||||
t = "tns:%s" % n
|
t = "tns:%s" % n
|
||||||
elif type(v) == dict:
|
elif isinstance(v, dict):
|
||||||
n = "%s%s" % (name, k)
|
n = "%s%s" % (name, k)
|
||||||
parse_element(n, v.items(), complex=True)
|
parse_element(n, v.items(), complex=True)
|
||||||
t = "tns:%s" % n
|
t = "tns:%s" % n
|
||||||
elif v in TYPE_MAP:
|
|
||||||
t = 'xsd:%s' % TYPE_MAP[v]
|
|
||||||
else:
|
else:
|
||||||
raise TypeError("unknown type %s for marshalling" % str(v))
|
raise TypeError("unknonw type %s for marshalling" % str(v))
|
||||||
e.add_attribute('type', t)
|
e.add_attribute('type', t)
|
||||||
|
|
||||||
parse_element("%s" % method, args and args.items())
|
parse_element("%s" % method, args and args.items())
|
||||||
|
|||||||
+1
-9
@@ -242,15 +242,7 @@ class Request(Storage):
|
|||||||
# parse POST variables on POST, PUT, BOTH only in post_vars
|
# parse POST variables on POST, PUT, BOTH only in post_vars
|
||||||
if body and not is_json and env.request_method in ('POST', 'PUT', 'DELETE', 'BOTH'):
|
if body and not is_json and env.request_method in ('POST', 'PUT', 'DELETE', 'BOTH'):
|
||||||
query_string = env.pop('QUERY_STRING', None)
|
query_string = env.pop('QUERY_STRING', None)
|
||||||
content_disposition = env.get('HTTP_CONTENT_DISPOSITION')
|
dpost = cgi.FieldStorage(fp=body, environ=env, keep_blank_values=1)
|
||||||
if content_disposition:
|
|
||||||
headers = {'content-disposition': content_disposition,
|
|
||||||
'content-type': env['CONTENT_TYPE'],
|
|
||||||
'content-length': env['CONTENT_LENGTH'],
|
|
||||||
}
|
|
||||||
else:
|
|
||||||
headers = None
|
|
||||||
dpost = cgi.FieldStorage(fp=body, environ=env, headers=headers, keep_blank_values=1)
|
|
||||||
try:
|
try:
|
||||||
post_vars.update(dpost)
|
post_vars.update(dpost)
|
||||||
except:
|
except:
|
||||||
|
|||||||
+7
-20
@@ -190,8 +190,7 @@ def URL(a=None,
|
|||||||
port=None,
|
port=None,
|
||||||
encode_embedded_slash=False,
|
encode_embedded_slash=False,
|
||||||
url_encode=True,
|
url_encode=True,
|
||||||
language=None,
|
language=None
|
||||||
hash_extension=True
|
|
||||||
):
|
):
|
||||||
"""
|
"""
|
||||||
generates a url '/a/c/f' corresponding to application a, controller c
|
generates a url '/a/c/f' corresponding to application a, controller c
|
||||||
@@ -340,8 +339,7 @@ def URL(a=None,
|
|||||||
if '.' in function:
|
if '.' in function:
|
||||||
function, extension = function.rsplit('.', 1)
|
function, extension = function.rsplit('.', 1)
|
||||||
|
|
||||||
# only include the extension as part of the variables for the hash if requested
|
function2 = '%s.%s' % (function, extension or 'html')
|
||||||
function2 = '%s.%s' % (function, extension or 'html') if hash_extension else function
|
|
||||||
|
|
||||||
if not (application and controller and function):
|
if not (application and controller and function):
|
||||||
raise SyntaxError('not enough information to build the url (%s %s %s)' % (application, controller, function))
|
raise SyntaxError('not enough information to build the url (%s %s %s)' % (application, controller, function))
|
||||||
@@ -418,7 +416,7 @@ def URL(a=None,
|
|||||||
return url
|
return url
|
||||||
|
|
||||||
|
|
||||||
def verifyURL(request, hmac_key=None, hash_vars=True, salt=None, user_signature=None, hash_extension=True):
|
def verifyURL(request, hmac_key=None, hash_vars=True, salt=None, user_signature=None):
|
||||||
"""
|
"""
|
||||||
Verifies that a request's args & vars have not been tampered with by the user
|
Verifies that a request's args & vars have not been tampered with by the user
|
||||||
|
|
||||||
@@ -479,19 +477,10 @@ def verifyURL(request, hmac_key=None, hash_vars=True, salt=None, user_signature=
|
|||||||
|
|
||||||
# always include all of the args
|
# always include all of the args
|
||||||
other = args and urllib_quote('/' + '/'.join([str(x) for x in args])) or ''
|
other = args and urllib_quote('/' + '/'.join([str(x) for x in args])) or ''
|
||||||
|
h_args = '/%s/%s/%s.%s%s' % (request.application,
|
||||||
# decide whether the extension should be part of the hash verification
|
|
||||||
h_extension = request.extension if hash_extension else ''
|
|
||||||
|
|
||||||
# only add a period to the extension when it exists otherwise empty
|
|
||||||
# extensions will fail to validate
|
|
||||||
if h_extension:
|
|
||||||
h_extension = '.%s' % (h_extension)
|
|
||||||
|
|
||||||
h_args = '/%s/%s/%s%s%s' % (request.application,
|
|
||||||
request.controller,
|
request.controller,
|
||||||
request.function,
|
request.function,
|
||||||
h_extension,
|
request.extension,
|
||||||
other)
|
other)
|
||||||
|
|
||||||
# but only include those vars specified (allows more flexibility for use with
|
# but only include those vars specified (allows more flexibility for use with
|
||||||
@@ -1461,10 +1450,8 @@ class SCRIPT(DIV):
|
|||||||
(fa, co) = self._xml()
|
(fa, co) = self._xml()
|
||||||
fa = to_bytes(fa)
|
fa = to_bytes(fa)
|
||||||
# no escaping of subcomponents
|
# no escaping of subcomponents
|
||||||
co = b'\n'.join(map(to_bytes,
|
co = b'\n'.join([to_bytes(component) for component in
|
||||||
# allow xml components (i.e. ASSIGNJS)
|
self.components])
|
||||||
map(lambda c: c.xml() if hasattr(c, 'xml') and callable(c.xml) else c,
|
|
||||||
self.components)))
|
|
||||||
if co:
|
if co:
|
||||||
# <script [attributes]><!--//--><![CDATA[//><!--
|
# <script [attributes]><!--//--><![CDATA[//><!--
|
||||||
# script body
|
# script body
|
||||||
|
|||||||
+20
-19
@@ -56,18 +56,19 @@ create_missing_folders()
|
|||||||
# set up logging for subsequent imports
|
# set up logging for subsequent imports
|
||||||
import logging.config
|
import logging.config
|
||||||
|
|
||||||
# do not need fancy graphical loggers when served by handler
|
# This needed to prevent exception on Python 2.5:
|
||||||
# (e.g. apache + mod_wsgi), speed up execution
|
# NameError: name 'gluon' is not defined
|
||||||
if not global_settings.web2py_runtime_handler:
|
# See http://bugs.python.org/issue1436
|
||||||
# attention!, the import Tkinter in messageboxhandler, changes locale ...
|
|
||||||
import gluon.messageboxhandler
|
# attention!, the import Tkinter in messageboxhandler, changes locale ...
|
||||||
# This needed to prevent exception on Python 2.5:
|
import gluon.messageboxhandler
|
||||||
# NameError: name 'gluon' is not defined
|
logging.gluon = gluon
|
||||||
# See http://bugs.python.org/issue1436
|
# so we must restore it! Thanks ozancag
|
||||||
logging.gluon = gluon
|
import locale
|
||||||
# so we must restore it! Thanks ozancag
|
locale.setlocale(locale.LC_CTYPE, "C") # IMPORTANT, web2py requires locale "C"
|
||||||
import locale
|
|
||||||
locale.setlocale(locale.LC_CTYPE, "C") # IMPORTANT, web2py requires locale "C"
|
exists = os.path.exists
|
||||||
|
pjoin = os.path.join
|
||||||
|
|
||||||
try:
|
try:
|
||||||
logging.config.fileConfig(abspath("logging.conf"))
|
logging.config.fileConfig(abspath("logging.conf"))
|
||||||
@@ -75,9 +76,6 @@ except: # fails on GAE or when logfile is missing
|
|||||||
logging.basicConfig()
|
logging.basicConfig()
|
||||||
logger = logging.getLogger("web2py")
|
logger = logging.getLogger("web2py")
|
||||||
|
|
||||||
exists = os.path.exists
|
|
||||||
pjoin = os.path.join
|
|
||||||
|
|
||||||
from gluon.restricted import RestrictedError
|
from gluon.restricted import RestrictedError
|
||||||
from gluon.http import HTTP, redirect
|
from gluon.http import HTTP, redirect
|
||||||
from gluon.globals import Request, Response, Session
|
from gluon.globals import Request, Response, Session
|
||||||
@@ -101,14 +99,17 @@ requests = 0 # gc timer
|
|||||||
|
|
||||||
try:
|
try:
|
||||||
version_info = read_file(pjoin(global_settings.gluon_parent, 'VERSION'))
|
version_info = read_file(pjoin(global_settings.gluon_parent, 'VERSION'))
|
||||||
web2py_version = global_settings.web2py_version = version_info.split()[-1].strip()
|
raw_version_string = version_info.split()[-1].strip()
|
||||||
|
global_settings.web2py_version = raw_version_string
|
||||||
|
web2py_version = global_settings.web2py_version
|
||||||
except:
|
except:
|
||||||
raise RuntimeError("Cannot determine web2py version")
|
raise RuntimeError("Cannot determine web2py version")
|
||||||
|
|
||||||
# do not need rocket nor HttpServer when served by handler
|
try:
|
||||||
# (e.g. apache + mod_wsgi), speed up execution and save memory
|
|
||||||
if not global_settings.web2py_runtime_handler:
|
|
||||||
from gluon import rocket
|
from gluon import rocket
|
||||||
|
except:
|
||||||
|
if not global_settings.web2py_runtime_gae:
|
||||||
|
logger.warn('unable to import Rocket')
|
||||||
|
|
||||||
load_routes()
|
load_routes()
|
||||||
|
|
||||||
|
|||||||
+1
-1
Submodule gluon/packages/dal updated: f66fb06813...732a63a496
+1
-1
Submodule gluon/packages/yatl updated: 6cb27d5ba6...5deb403a9e
+394
-607
File diff suppressed because it is too large
Load Diff
+1
-5
@@ -23,11 +23,7 @@ HTTP_SERVER_SOFTWARE = '%s Python/%s' % (
|
|||||||
BUF_SIZE = 16384
|
BUF_SIZE = 16384
|
||||||
SOCKET_TIMEOUT = 10 # in secs
|
SOCKET_TIMEOUT = 10 # in secs
|
||||||
THREAD_STOP_CHECK_INTERVAL = 1 # in secs, How often should threads check for a server stop message?
|
THREAD_STOP_CHECK_INTERVAL = 1 # in secs, How often should threads check for a server stop message?
|
||||||
if hasattr(sys, 'frozen'):
|
IS_JYTHON = platform.system() == 'Java' # Handle special cases for Jython
|
||||||
# py2installer
|
|
||||||
IS_JYTHON = False
|
|
||||||
else:
|
|
||||||
IS_JYTHON = platform.system() == 'Java' # Handle special cases for Jython
|
|
||||||
IGNORE_ERRORS_ON_CLOSE = set([errno.ECONNABORTED, errno.ECONNRESET])
|
IGNORE_ERRORS_ON_CLOSE = set([errno.ECONNABORTED, errno.ECONNRESET])
|
||||||
DEFAULT_LISTEN_QUEUE_SIZE = 5
|
DEFAULT_LISTEN_QUEUE_SIZE = 5
|
||||||
DEFAULT_MIN_THREADS = 10
|
DEFAULT_MIN_THREADS = 10
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ def custom_json(o):
|
|||||||
elif isinstance(o, decimal.Decimal):
|
elif isinstance(o, decimal.Decimal):
|
||||||
return float(o)
|
return float(o)
|
||||||
elif isinstance(o, (bytes, bytearray)):
|
elif isinstance(o, (bytes, bytearray)):
|
||||||
return str(o) if hasattr(str, 'decode') else str(o, encoding='utf-8')
|
return str(o)
|
||||||
elif isinstance(o, lazyT):
|
elif isinstance(o, lazyT):
|
||||||
return str(o)
|
return str(o)
|
||||||
elif isinstance(o, XmlComponent):
|
elif isinstance(o, XmlComponent):
|
||||||
|
|||||||
@@ -43,7 +43,3 @@ global_settings.is_source = os.path.exists(os.path.join(
|
|||||||
global_settings.gluon_parent, 'web2py.py'))
|
global_settings.gluon_parent, 'web2py.py'))
|
||||||
|
|
||||||
global_settings.is_py2 = PY2
|
global_settings.is_py2 = PY2
|
||||||
|
|
||||||
# allow admin app for clients on trusted LAN when over plain http,
|
|
||||||
# default is to allow only from localhost or when serving https
|
|
||||||
#global_settings.trusted_lan_prefix = '192.168.0.'
|
|
||||||
|
|||||||
+1
-20
@@ -20,7 +20,6 @@ import logging
|
|||||||
import types
|
import types
|
||||||
import re
|
import re
|
||||||
import glob
|
import glob
|
||||||
import site
|
|
||||||
import traceback
|
import traceback
|
||||||
import gluon.fileutils as fileutils
|
import gluon.fileutils as fileutils
|
||||||
from gluon.settings import global_settings
|
from gluon.settings import global_settings
|
||||||
@@ -241,16 +240,13 @@ def run(
|
|||||||
if not cron_job and not scheduler_job and \
|
if not cron_job and not scheduler_job and \
|
||||||
sys.stdin and not sys.stdin.name == '/dev/null':
|
sys.stdin and not sys.stdin.name == '/dev/null':
|
||||||
confirm = raw_input(
|
confirm = raw_input(
|
||||||
'application %s does not exist, create (y/N)?' % a)
|
'application %s does not exist, create (y/n)?' % a)
|
||||||
else:
|
else:
|
||||||
logging.warn('application does not exist and will not be created')
|
logging.warn('application does not exist and will not be created')
|
||||||
return
|
return
|
||||||
if confirm.lower() in ('y', 'yes'):
|
if confirm.lower() in ('y', 'yes'):
|
||||||
os.mkdir(adir)
|
os.mkdir(adir)
|
||||||
fileutils.create_app(adir)
|
fileutils.create_app(adir)
|
||||||
else:
|
|
||||||
logging.warn('application folder does not exist and has not been created as requested')
|
|
||||||
return
|
|
||||||
|
|
||||||
if force_migrate:
|
if force_migrate:
|
||||||
c = 'appadmin' # Load all models (hack already used for appadmin controller)
|
c = 'appadmin' # Load all models (hack already used for appadmin controller)
|
||||||
@@ -307,11 +303,6 @@ def run(
|
|||||||
|
|
||||||
if import_models:
|
if import_models:
|
||||||
BaseAdapter.close_all_instances('commit')
|
BaseAdapter.close_all_instances('commit')
|
||||||
except SystemExit:
|
|
||||||
print(traceback.format_exc())
|
|
||||||
if import_models:
|
|
||||||
BaseAdapter.close_all_instances('rollback')
|
|
||||||
raise
|
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
if import_models:
|
if import_models:
|
||||||
@@ -321,11 +312,6 @@ def run(
|
|||||||
exec(python_code, _env)
|
exec(python_code, _env)
|
||||||
if import_models:
|
if import_models:
|
||||||
BaseAdapter.close_all_instances('commit')
|
BaseAdapter.close_all_instances('commit')
|
||||||
except SystemExit:
|
|
||||||
print(traceback.format_exc())
|
|
||||||
if import_models:
|
|
||||||
BaseAdapter.close_all_instances('rollback')
|
|
||||||
raise
|
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
if import_models:
|
if import_models:
|
||||||
@@ -335,11 +321,6 @@ def run(
|
|||||||
execfile("scripts/migrator.py", _env)
|
execfile("scripts/migrator.py", _env)
|
||||||
if import_models:
|
if import_models:
|
||||||
BaseAdapter.close_all_instances('commit')
|
BaseAdapter.close_all_instances('commit')
|
||||||
except SystemExit:
|
|
||||||
print(traceback.format_exc())
|
|
||||||
if import_models:
|
|
||||||
BaseAdapter.close_all_instances('rollback')
|
|
||||||
raise
|
|
||||||
except:
|
except:
|
||||||
print(traceback.format_exc())
|
print(traceback.format_exc())
|
||||||
if import_models:
|
if import_models:
|
||||||
|
|||||||
+9
-13
@@ -99,7 +99,7 @@ class CacheRepresenter(object):
|
|||||||
nvalue = field.represent(value, row[field.tablename])
|
nvalue = field.represent(value, row[field.tablename])
|
||||||
except KeyError:
|
except KeyError:
|
||||||
nvalue = None
|
nvalue = None
|
||||||
if isinstance(field.represent, _repr_ref): # BKR ISSUE/2312 20200422
|
if isinstance(field, _repr_ref):
|
||||||
cache[field][value] = nvalue
|
cache[field][value] = nvalue
|
||||||
return nvalue
|
return nvalue
|
||||||
|
|
||||||
@@ -1330,7 +1330,7 @@ class SQLFORM(FORM):
|
|||||||
# - user not trying to upload a new file
|
# - user not trying to upload a new file
|
||||||
# - there is existing file and user is not trying to delete it
|
# - there is existing file and user is not trying to delete it
|
||||||
# this is because removing the file may not pass validation
|
# this is because removing the file may not pass validation
|
||||||
for key in list(self.errors):
|
for key in self.errors.keys():
|
||||||
if key in self.table \
|
if key in self.table \
|
||||||
and self.table[key].type == 'upload' \
|
and self.table[key].type == 'upload' \
|
||||||
and request_vars.get(key, None) in (None, '') \
|
and request_vars.get(key, None) in (None, '') \
|
||||||
@@ -1501,7 +1501,7 @@ class SQLFORM(FORM):
|
|||||||
if readonly and not ignore_rw and not field.readable:
|
if readonly and not ignore_rw and not field.readable:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if record and fieldname not in [x.name for x in extra_fields]:
|
if record:
|
||||||
default = record[fieldname]
|
default = record[fieldname]
|
||||||
else:
|
else:
|
||||||
default = field.default
|
default = field.default
|
||||||
@@ -2667,7 +2667,7 @@ class SQLFORM(FORM):
|
|||||||
if export_type:
|
if export_type:
|
||||||
order = request.vars.order or ''
|
order = request.vars.order or ''
|
||||||
if sortable:
|
if sortable:
|
||||||
if order:
|
if order and not order == 'None':
|
||||||
otablename, ofieldname = order.split('~')[-1].split('.', 1)
|
otablename, ofieldname = order.split('~')[-1].split('.', 1)
|
||||||
sort_field = db[otablename][ofieldname]
|
sort_field = db[otablename][ofieldname]
|
||||||
orderby = sort_field if order[:1] != '~' else ~sort_field
|
orderby = sort_field if order[:1] != '~' else ~sort_field
|
||||||
@@ -2800,7 +2800,7 @@ class SQLFORM(FORM):
|
|||||||
order = request.vars.order or ''
|
order = request.vars.order or ''
|
||||||
asc_icon, desc_icon = sorter_icons
|
asc_icon, desc_icon = sorter_icons
|
||||||
if sortable:
|
if sortable:
|
||||||
if order:
|
if order and not order == 'None':
|
||||||
otablename, ofieldname = order.split('~')[-1].split('.', 1)
|
otablename, ofieldname = order.split('~')[-1].split('.', 1)
|
||||||
sort_field = db[otablename][ofieldname]
|
sort_field = db[otablename][ofieldname]
|
||||||
orderby = sort_field if order[:1] != '~' else ~sort_field
|
orderby = sort_field if order[:1] != '~' else ~sort_field
|
||||||
@@ -2820,14 +2820,14 @@ class SQLFORM(FORM):
|
|||||||
if key == order.lstrip('~'):
|
if key == order.lstrip('~'):
|
||||||
if inverted:
|
if inverted:
|
||||||
if key == order:
|
if key == order:
|
||||||
marker = asc_icon
|
key, marker = 'None', asc_icon
|
||||||
else:
|
else:
|
||||||
key, marker = order[1:], desc_icon
|
key, marker = order[1:], desc_icon
|
||||||
else:
|
else:
|
||||||
if key == order:
|
if key == order:
|
||||||
key, marker = '~' + order, asc_icon
|
key, marker = '~' + order, asc_icon
|
||||||
else:
|
else:
|
||||||
marker = desc_icon
|
key, marker = 'None', desc_icon
|
||||||
elif inverted and key == str(field):
|
elif inverted and key == str(field):
|
||||||
key = '~' + key
|
key = '~' + key
|
||||||
header = A(header, marker, _href=url(vars=dict(
|
header = A(header, marker, _href=url(vars=dict(
|
||||||
@@ -3393,7 +3393,6 @@ class SQLTABLE(TABLE):
|
|||||||
linkto: URL (or lambda to generate a URL) to edit individual records
|
linkto: URL (or lambda to generate a URL) to edit individual records
|
||||||
upload: URL to download uploaded files
|
upload: URL to download uploaded files
|
||||||
orderby: Add an orderby link to column headers.
|
orderby: Add an orderby link to column headers.
|
||||||
query: Query string to support orderby headers.
|
|
||||||
headers: dictionary of headers to headers redefinions
|
headers: dictionary of headers to headers redefinions
|
||||||
headers can also be a string to generate the headers from data
|
headers can also be a string to generate the headers from data
|
||||||
for now only headers="fieldname:capitalize",
|
for now only headers="fieldname:capitalize",
|
||||||
@@ -3429,7 +3428,6 @@ class SQLTABLE(TABLE):
|
|||||||
linkto=None,
|
linkto=None,
|
||||||
upload=None,
|
upload=None,
|
||||||
orderby=None,
|
orderby=None,
|
||||||
query='',
|
|
||||||
headers={},
|
headers={},
|
||||||
truncate=16,
|
truncate=16,
|
||||||
columns=None,
|
columns=None,
|
||||||
@@ -3501,10 +3499,8 @@ class SQLTABLE(TABLE):
|
|||||||
attrcol.update(_class=coldict['class'])
|
attrcol.update(_class=coldict['class'])
|
||||||
row.append(TH(coldict['label'], **attrcol))
|
row.append(TH(coldict['label'], **attrcol))
|
||||||
elif orderby:
|
elif orderby:
|
||||||
link = th_link + '?orderby=' + c
|
row.append(TH(A(headers.get(c, c),
|
||||||
if query:
|
_href=th_link + '?orderby=' + c, cid=cid)))
|
||||||
link += '&query=' + query
|
|
||||||
row.append(TH(A(headers.get(c, c), _href=link, cid=cid)))
|
|
||||||
else:
|
else:
|
||||||
row.append(TH(headers.get(c, re.sub(self.REGEX_ALIAS_MATCH, r'\2', c))))
|
row.append(TH(headers.get(c, re.sub(self.REGEX_ALIAS_MATCH, r'\2', c))))
|
||||||
|
|
||||||
|
|||||||
@@ -188,7 +188,7 @@ class TestBareHelpers(unittest.TestCase):
|
|||||||
XML('<h1>HelloWorld</h1>').__repr__())
|
XML('<h1>HelloWorld</h1>').__repr__())
|
||||||
# bug check for the sanitizer for closing no-close tags
|
# bug check for the sanitizer for closing no-close tags
|
||||||
self.assertEqual(XML('<p>Test</p><br/><p>Test</p><br/>', sanitize=True).xml(),
|
self.assertEqual(XML('<p>Test</p><br/><p>Test</p><br/>', sanitize=True).xml(),
|
||||||
XML('<p>Test</p><br/><p>Test</p><br/>').xml())
|
XML('<p>Test</p><br /><p>Test</p><br />').xml())
|
||||||
# basic flatten test
|
# basic flatten test
|
||||||
self.assertEqual(XML('<p>Test</p>').flatten(), '<p>Test</p>')
|
self.assertEqual(XML('<p>Test</p>').flatten(), '<p>Test</p>')
|
||||||
self.assertEqual(XML('<p>Test</p>').flatten(render=lambda text, tag, attr: text), '<p>Test</p>')
|
self.assertEqual(XML('<p>Test</p>').flatten(render=lambda text, tag, attr: text), '<p>Test</p>')
|
||||||
|
|||||||
+10
-15
@@ -816,15 +816,7 @@ class Mail(object):
|
|||||||
server.login(*self.settings.login.split(':', 1))
|
server.login(*self.settings.login.split(':', 1))
|
||||||
result = server.sendmail(sender, to, payload.as_string())
|
result = server.sendmail(sender, to, payload.as_string())
|
||||||
finally:
|
finally:
|
||||||
# do not want to hide errors raising some exception here
|
server.quit()
|
||||||
try:
|
|
||||||
server.quit()
|
|
||||||
except smtplib.SMTPException:
|
|
||||||
# ensure to close any socket with SMTP server
|
|
||||||
try:
|
|
||||||
server.close()
|
|
||||||
except Exception:
|
|
||||||
pass
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
logger.warning('Mail.send failure:%s' % e)
|
logger.warning('Mail.send failure:%s' % e)
|
||||||
self.result = result
|
self.result = result
|
||||||
@@ -992,15 +984,15 @@ def addrow(form, a, b, c, style, _id, position=-1):
|
|||||||
DIV(b, SPAN(c, _class='inline-help'),
|
DIV(b, SPAN(c, _class='inline-help'),
|
||||||
_class='controls'),
|
_class='controls'),
|
||||||
_class='control-group', _id=_id))
|
_class='control-group', _id=_id))
|
||||||
elif style in ("bootstrap3_inline", "bootstrap4_inline"):
|
elif style == "bootstrap3_inline":
|
||||||
form[0].insert(position, DIV(LABEL(a, _class='control-label col-sm-3'),
|
form[0].insert(position, DIV(LABEL(a, _class='control-label col-sm-3'),
|
||||||
DIV(b, SPAN(c, _class='help-block'),
|
DIV(b, SPAN(c, _class='help-block'),
|
||||||
_class='col-sm-9'),
|
_class='col-sm-9'),
|
||||||
_class='form-group row', _id=_id))
|
_class='form-group', _id=_id))
|
||||||
elif style in ("bootstrap3_stacked", "bootstrap4_stacked"):
|
elif style == "bootstrap3_stacked":
|
||||||
form[0].insert(position, DIV(LABEL(a, _class='control-label'),
|
form[0].insert(position, DIV(LABEL(a, _class='control-label'),
|
||||||
b, SPAN(c, _class='help-block'),
|
b, SPAN(c, _class='help-block'),
|
||||||
_class='form-group row', _id=_id))
|
_class='form-group', _id=_id))
|
||||||
else:
|
else:
|
||||||
form[0].insert(position, TR(TD(LABEL(a), _class='w2p_fl'),
|
form[0].insert(position, TR(TD(LABEL(a), _class='w2p_fl'),
|
||||||
TD(b, _class='w2p_fw'),
|
TD(b, _class='w2p_fw'),
|
||||||
@@ -3930,7 +3922,7 @@ class Auth(AuthAPI):
|
|||||||
return self.has_permission(name, table_name, record_id)
|
return self.has_permission(name, table_name, record_id)
|
||||||
return self.requires(has_permission, otherwise=otherwise)
|
return self.requires(has_permission, otherwise=otherwise)
|
||||||
|
|
||||||
def requires_signature(self, otherwise=None, hash_vars=True, hash_extension=True):
|
def requires_signature(self, otherwise=None, hash_vars=True):
|
||||||
"""
|
"""
|
||||||
Decorator that prevents access to action if not logged in or
|
Decorator that prevents access to action if not logged in or
|
||||||
if user logged in is not a member of group_id.
|
if user logged in is not a member of group_id.
|
||||||
@@ -3938,7 +3930,7 @@ class Auth(AuthAPI):
|
|||||||
group_id is calculated.
|
group_id is calculated.
|
||||||
"""
|
"""
|
||||||
def verify():
|
def verify():
|
||||||
return URL.verify(current.request, user_signature=True, hash_vars=hash_vars, hash_extension=True)
|
return URL.verify(current.request, user_signature=True, hash_vars=hash_vars)
|
||||||
return self.requires(verify, otherwise)
|
return self.requires(verify, otherwise)
|
||||||
|
|
||||||
def accessible_query(self, name, table, user_id=None):
|
def accessible_query(self, name, table, user_id=None):
|
||||||
@@ -5613,6 +5605,9 @@ class Expose(object):
|
|||||||
and file creation under `base`.
|
and file creation under `base`.
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# why would this not be callable? but otherwise tests do not pass
|
||||||
|
if current.session and callable(current.session.forget):
|
||||||
|
current.session.forget()
|
||||||
self.follow_symlink_out = follow_symlink_out
|
self.follow_symlink_out = follow_symlink_out
|
||||||
self.base = self.normalize_path(
|
self.base = self.normalize_path(
|
||||||
base or os.path.join(current.request.folder, 'static'))
|
base or os.path.join(current.request.folder, 'static'))
|
||||||
|
|||||||
+9
-13
@@ -704,9 +704,14 @@ def start():
|
|||||||
run_system_tests(options)
|
run_system_tests(options)
|
||||||
|
|
||||||
if options.quiet:
|
if options.quiet:
|
||||||
# mute existing loggers, to do that iterate
|
# to prevent writes on stdout set a null stream
|
||||||
# over all loggers (root logger included) and remove
|
class NullFile(object):
|
||||||
# attached logging.StreamHandler instances currently
|
def write(self, x):
|
||||||
|
pass
|
||||||
|
sys.stdout = NullFile()
|
||||||
|
# but still has to mute existing loggers, to do that iterate
|
||||||
|
# over all existing loggers (root logger included) and remove
|
||||||
|
# all attached logging.StreamHandler instances currently
|
||||||
# streaming on sys.stdout or sys.stderr
|
# streaming on sys.stdout or sys.stderr
|
||||||
loggers = [logging.getLogger()]
|
loggers = [logging.getLogger()]
|
||||||
loggers.extend(logging.Logger.manager.loggerDict.values())
|
loggers.extend(logging.Logger.manager.loggerDict.values())
|
||||||
@@ -716,18 +721,9 @@ def start():
|
|||||||
if isinstance(h, logging.StreamHandler) and \
|
if isinstance(h, logging.StreamHandler) and \
|
||||||
h.stream in (sys.stdout, sys.stderr):
|
h.stream in (sys.stdout, sys.stderr):
|
||||||
l.removeHandler(h)
|
l.removeHandler(h)
|
||||||
# this is to avoid the warning
|
|
||||||
# ``No handlers could be found for logger "..."``
|
|
||||||
# emitted by logging module when no handler is found
|
|
||||||
logging.Logger.manager.emittedNoHandlerWarning = 1
|
|
||||||
# to prevent writes on stdout set a null stream
|
|
||||||
class NullFile(object):
|
|
||||||
def write(self, x):
|
|
||||||
pass
|
|
||||||
sys.stdout = NullFile()
|
|
||||||
# NOTE: stderr.write() is still working
|
# NOTE: stderr.write() is still working
|
||||||
|
|
||||||
elif not options.no_banner:
|
if not options.no_banner:
|
||||||
# banner
|
# banner
|
||||||
print(ProgramName)
|
print(ProgramName)
|
||||||
print(ProgramAuthor)
|
print(ProgramAuthor)
|
||||||
|
|||||||
@@ -62,9 +62,6 @@ if not os.path.isdir('applications'):
|
|||||||
|
|
||||||
sys.path = [path] + [p for p in sys.path if not p == path]
|
sys.path = [path] + [p for p in sys.path if not p == path]
|
||||||
|
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
|
|
||||||
wsgiref.handlers.CGIHandler().run(gluon.main.wsgibase)
|
wsgiref.handlers.CGIHandler().run(gluon.main.wsgibase)
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ if not os.path.isdir('applications'):
|
|||||||
|
|
||||||
sys.path = [path] + [p for p in sys.path if not p == path]
|
sys.path = [path] + [p for p in sys.path if not p == path]
|
||||||
|
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
import gluon.contrib.gateways.fcgi as fcgi
|
import gluon.contrib.gateways.fcgi as fcgi
|
||||||
|
|
||||||
@@ -54,6 +51,7 @@ else:
|
|||||||
application = gluon.main.wsgibase
|
application = gluon.main.wsgibase
|
||||||
|
|
||||||
if SOFTCRON:
|
if SOFTCRON:
|
||||||
|
from gluon.settings import global_settings
|
||||||
global_settings.web2py_crontype = 'soft'
|
global_settings.web2py_crontype = 'soft'
|
||||||
|
|
||||||
fcgi.WSGIServer(application, bindAddress='/tmp/fcgi.sock').run()
|
fcgi.WSGIServer(application, bindAddress='/tmp/fcgi.sock').run()
|
||||||
|
|||||||
@@ -49,15 +49,14 @@ from google.appengine.ext import webapp
|
|||||||
from google.appengine.ext.webapp.util import run_wsgi_app
|
from google.appengine.ext.webapp.util import run_wsgi_app
|
||||||
|
|
||||||
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
global_settings.web2py_runtime_gae = True
|
global_settings.web2py_runtime_gae = True
|
||||||
global_settings.db_sessions = True
|
global_settings.db_sessions = True
|
||||||
if os.environ.get('SERVER_SOFTWARE', '').startswith('Devel'):
|
if os.environ.get('SERVER_SOFTWARE', '').startswith('Devel'):
|
||||||
global_settings.web2py_runtime = 'gae:development'
|
(global_settings.web2py_runtime, DEBUG) = \
|
||||||
DEBUG = True
|
('gae:development', True)
|
||||||
else:
|
else:
|
||||||
global_settings.web2py_runtime = 'gae:production'
|
(global_settings.web2py_runtime, DEBUG) = \
|
||||||
DEBUG = False
|
('gae:production', False)
|
||||||
|
|
||||||
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ def __ExtensionFactory__():
|
|||||||
if not os.path.isdir('applications'):
|
if not os.path.isdir('applications'):
|
||||||
raise RuntimeError('Running from the wrong folder')
|
raise RuntimeError('Running from the wrong folder')
|
||||||
sys.path = [path] + [p for p in sys.path if not p == path]
|
sys.path = [path] + [p for p in sys.path if not p == path]
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
import isapi_wsgi
|
import isapi_wsgi
|
||||||
application = gluon.main.wsgibase
|
application = gluon.main.wsgibase
|
||||||
|
|||||||
@@ -40,9 +40,6 @@ if not os.path.isdir('applications'):
|
|||||||
|
|
||||||
sys.path = [path] + [p for p in sys.path if not p == path]
|
sys.path = [path] + [p for p in sys.path if not p == path]
|
||||||
|
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -53,9 +53,6 @@ if not os.path.isdir('applications'):
|
|||||||
|
|
||||||
sys.path = [path] + [p for p in sys.path if not p == path]
|
sys.path = [path] + [p for p in sys.path if not p == path]
|
||||||
|
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
|
|
||||||
# uncomment one of the two imports below depending on the SCGIWSGI server installed
|
# uncomment one of the two imports below depending on the SCGIWSGI server installed
|
||||||
@@ -73,6 +70,7 @@ else:
|
|||||||
application = wsgiapp
|
application = wsgiapp
|
||||||
|
|
||||||
if SOFTCRON:
|
if SOFTCRON:
|
||||||
|
from gluon.settings import global_settings
|
||||||
global_settings.web2py_crontype = 'soft'
|
global_settings.web2py_crontype = 'soft'
|
||||||
|
|
||||||
# uncomment one of the two rows below depending on the SCGIWSGI server installed
|
# uncomment one of the two rows below depending on the SCGIWSGI server installed
|
||||||
|
|||||||
@@ -21,8 +21,6 @@ from gevent import monkey
|
|||||||
monkey.patch_all()
|
monkey.patch_all()
|
||||||
|
|
||||||
def run(options):
|
def run(options):
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
if options.password != '<recycle>':
|
if options.password != '<recycle>':
|
||||||
gluon.main.save_password(options.password, int(options.port))
|
gluon.main.save_password(options.password, int(options.port))
|
||||||
|
|||||||
@@ -26,9 +26,6 @@ if not os.path.isdir('applications'):
|
|||||||
|
|
||||||
sys.path = [path] + [p for p in sys.path if not p == path]
|
sys.path = [path] + [p for p in sys.path if not p == path]
|
||||||
|
|
||||||
from gluon.settings import global_settings
|
|
||||||
global_settings.web2py_runtime_handler = True
|
|
||||||
|
|
||||||
import gluon.main
|
import gluon.main
|
||||||
|
|
||||||
if LOGGING:
|
if LOGGING:
|
||||||
@@ -39,4 +36,5 @@ else:
|
|||||||
application = gluon.main.wsgibase
|
application = gluon.main.wsgibase
|
||||||
|
|
||||||
if SOFTCRON:
|
if SOFTCRON:
|
||||||
|
from gluon.settings import global_settings
|
||||||
global_settings.web2py_crontype = 'soft'
|
global_settings.web2py_crontype = 'soft'
|
||||||
|
|||||||
+12
-12
@@ -41,7 +41,7 @@ from __future__ import with_statement
|
|||||||
from gluon import current
|
from gluon import current
|
||||||
from gluon.storage import Storage
|
from gluon.storage import Storage
|
||||||
from gluon._compat import pickle
|
from gluon._compat import pickle
|
||||||
|
from optparse import OptionParser
|
||||||
import datetime
|
import datetime
|
||||||
import stat
|
import stat
|
||||||
import time
|
import time
|
||||||
@@ -62,12 +62,13 @@ class SessionSet(object):
|
|||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
"""Get session files/records."""
|
"""Get session files/records."""
|
||||||
raise NotImplementedError()
|
raise NotImplementedError
|
||||||
|
|
||||||
def trash(self):
|
def trash(self):
|
||||||
"""Trash expired sessions."""
|
"""Trash expired sessions."""
|
||||||
now = datetime.datetime.now()
|
now = datetime.datetime.now()
|
||||||
for item in self.get():
|
for item in self.get():
|
||||||
|
status = 'OK'
|
||||||
last_visit = item.last_visit_default()
|
last_visit = item.last_visit_default()
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -87,18 +88,16 @@ class SessionSet(object):
|
|||||||
if age > self.expiration or not self.expiration:
|
if age > self.expiration or not self.expiration:
|
||||||
item.delete()
|
item.delete()
|
||||||
status = 'trashed'
|
status = 'trashed'
|
||||||
else:
|
|
||||||
status = 'OK'
|
|
||||||
|
|
||||||
if self.verbose > 1:
|
if self.verbose > 1:
|
||||||
print('key: %s' % item)
|
print('key: %s' % str(item))
|
||||||
print('expiration: %s seconds' % self.expiration)
|
print('expiration: %s seconds' % self.expiration)
|
||||||
print('last visit: %s' % last_visit)
|
print('last visit: %s' % str(last_visit))
|
||||||
print('age: %s seconds' % age)
|
print('age: %s seconds' % age)
|
||||||
print('status: %s' % status)
|
print('status: %s' % status)
|
||||||
print('')
|
print('')
|
||||||
elif self.verbose > 0:
|
elif self.verbose > 0:
|
||||||
print('%s %s' % (item, status))
|
print('%s %s' % (str(item), status))
|
||||||
|
|
||||||
|
|
||||||
class SessionSetDb(SessionSet):
|
class SessionSetDb(SessionSet):
|
||||||
@@ -180,8 +179,8 @@ class SessionFile(object):
|
|||||||
|
|
||||||
def get(self):
|
def get(self):
|
||||||
session = Storage()
|
session = Storage()
|
||||||
with open(self.filename, 'rb') as f:
|
with open(self.filename, 'rb+') as f:
|
||||||
session.update(pickle.load(f))
|
session.update(cPickle.load(f))
|
||||||
return session
|
return session
|
||||||
|
|
||||||
def last_visit_default(self):
|
def last_visit_default(self):
|
||||||
@@ -199,7 +198,8 @@ def total_seconds(delta):
|
|||||||
Args:
|
Args:
|
||||||
delta: datetime.timedelta instance.
|
delta: datetime.timedelta instance.
|
||||||
"""
|
"""
|
||||||
return (delta.microseconds + (delta.seconds + (delta.days * 86400)) * 1000000) / 1e6
|
return (delta.microseconds + (delta.seconds + (delta.days * 24 * 3600)) *
|
||||||
|
10 ** 6) / 10 ** 6
|
||||||
|
|
||||||
def single_loop(expiration=None, force=False, verbose=False):
|
def single_loop(expiration=None, force=False, verbose=False):
|
||||||
if expiration is None:
|
if expiration is None:
|
||||||
@@ -216,9 +216,9 @@ def single_loop(expiration=None, force=False, verbose=False):
|
|||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""Main processing."""
|
"""Main processing."""
|
||||||
from optparse import OptionParser
|
|
||||||
|
|
||||||
parser = OptionParser(usage="%%prog [options]\nVersion: %s" % VERSION)
|
usage = '%prog [options]' + '\nVersion: %s' % VERSION
|
||||||
|
parser = OptionParser(usage=usage)
|
||||||
|
|
||||||
parser.add_option('-f', '--force',
|
parser.add_option('-f', '--force',
|
||||||
action='store_true', dest='force', default=False,
|
action='store_true', dest='force', default=False,
|
||||||
|
|||||||
@@ -19,9 +19,6 @@ else:
|
|||||||
# process -f (--folder) option
|
# process -f (--folder) option
|
||||||
if '-f' in sys.argv:
|
if '-f' in sys.argv:
|
||||||
fi = sys.argv.index('-f')
|
fi = sys.argv.index('-f')
|
||||||
# maybe session2trash arg
|
|
||||||
if '-A' in sys.argv and fi > sys.argv.index('-A'):
|
|
||||||
fi = None
|
|
||||||
elif '--folder' in sys.argv:
|
elif '--folder' in sys.argv:
|
||||||
fi = sys.argv.index('--folder')
|
fi = sys.argv.index('--folder')
|
||||||
else:
|
else:
|
||||||
|
|||||||
Reference in New Issue
Block a user