From 3fe797ce6030e74a45007ae86301757ac9511b1b Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Mon, 1 Jul 2019 22:42:27 +0200 Subject: [PATCH 01/35] full docs --- extras/build_web2py/README_mac.md | 50 +++++++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 extras/build_web2py/README_mac.md diff --git a/extras/build_web2py/README_mac.md b/extras/build_web2py/README_mac.md new file mode 100644 index 00000000..ae19e779 --- /dev/null +++ b/extras/build_web2py/README_mac.md @@ -0,0 +1,50 @@ +## MacOS binaries + +The MacOS binaries contain Python 3.7.3 (or 2.7.16) 64 bit with all the needed modules and the web2py in the specified version: + you don't need anything else to run them on MacOS! After uncompressing the zip file, you just need to click on the web2py icon inside. + +They were produced on MacOS Sierra 10.12.6 + security update 2019.001. + +## Full MacOS build recipe + +1. grab and install the official Python program: we've got version 3.7.3 or 2.7.16 (64 bit). If you've chosen python 2, change pip3 +with pip, and python3 with python in the following instructions... + +2. Open a terminal, update tools with: + +"python3 -m pip install --upgrade pip" +"pip3 install --upgrade setuptools" + + +3. install PyInstaller with: +sudo -H pip3 install pyinstaller (we've got PyInstaller-3.4 ) + +4. additional (but not required) packages: +(only for python 2: install Homebrew from https://brew.sh/#install , then 'brew install unixodbc' ) +pip3 install psycopg2-binary = psycopg2-2.7.7 +pip3 install pyodbc = pyodbc-4.0.26-cp37-cp37m +pip3 install python-ldap (on the windows message, accept to install the "Command line developer tools"). Rerun: +pip3 install python-ldap + +5. grab latest web2py source from https://mdipierro.pythonanywhere.com/examples/static/web2py_src.zip + (you need at least 2.18.3 for needed changes in gluon\admin.py). Open it to uncompress, in this example on Desktop/web2py + + +6. take the file build_web2py.py and web2py.mac.spec from this folder and place it on the Desktop/web2py folder + +7. edit the file /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PyInstaller/hooks/hook-_tkinter.py + and change one of its line according to https://github.com/pyinstaller/pyinstaller/pull/3830 + +8. (optional, for having a full working interactive shell) change the fake site.py module included within the PyInstaller installation + with the content of the files web2py.site_37.py or web2py.site_27.py from this folder - see comments inside these files for details + +9. open a terminal, goto Desktop/web2py and run: + +python3 build_web2py.py + +10. if everything is fine, you'll obtain web2py_macos.zip on the Desktop/web2py folder. Inside it, there is the web2py program with + both the CMD version and the APP version. + +## Gothca + +Unfortunately, the APP version is still not working - see https://github.com/pyinstaller/pyinstaller/issues/3820 . From c247e740a2d6494b06d195040fba7832fc00ee46 Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Mon, 1 Jul 2019 22:49:09 +0200 Subject: [PATCH 02/35] full docs --- extras/build_web2py/README_win.md | 47 +++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 extras/build_web2py/README_win.md diff --git a/extras/build_web2py/README_win.md b/extras/build_web2py/README_win.md new file mode 100644 index 00000000..fe5f797b --- /dev/null +++ b/extras/build_web2py/README_win.md @@ -0,0 +1,47 @@ +## Windows binaries + +The windows binaries contain Python 64 bit version 3.7.3 or 2.7.16 with all the needed modules and the web2py in the specified version. +You don't need anything else to run them on Windows. +At least on Windows 7, if you get an error stating that "api-ms-win-crt-runtime-l1-1-0.dll is missing" you have only to install the +free and official "Visual C++ Redistributable for Visual Studio" as described later + + +## Full Windows build recipe + +1. get a clean Windows 10 (Windows 10 Professional English build 1809 64 bit, under Virtualbox in our case) +2. grab and install the official Python program: we've got version 3.7.3 or 2.7.16, 64 bit +(https://www.python.org/ftp/python/3.7.2/python-3.7.2-amd64.exe ) + select "add Python 3.7 to PATH" during its setup if Python 3. +For Python 2 you need to manually add the folders for python27 and python27\Scripts to the system path. +3. update tools with +"python -m pip install --upgrade pip" +"pip install --upgrade setuptools" +4. download and install python-win32, which is needed for web2py to work with all features enabled +(https://github.com/mhammond/pywin32/releases/download/b224/pywin32-224.win-amd64-py3.7.exe) +5. grab latest web2py source from https://mdipierro.pythonanywhere.com/examples/static/web2py_src.zip (you need at least 2.18.3 for +needed changes in gluon\admin.py). Unzip it in a dedicated folder, in this example C:\web2py - so that you have +C:\web2py\web2py.py inside) +6. install PyInstaller with: + pip install pyinstaller (we've got PyInstaller-3.4.tar.gz ) +7. download and install the free Microsoft Visual C++ Redistributable per Visual Studio 2017, 64 bit version, from + https://aka.ms/vs/15/release/vc_redist.x64.exe +8. additional (but not required) packages to work better in the Windows world: +pip install psycopg2 = psycopg2-2.7.7-cp37-cp37m-win_amd64.whl +pip install pyodbc = pyodbc-4.0.26-cp37-cp37m-win_amd64.whl +download the file python_ldap-3.1.0-cp37-cp37m-win_amd64.whl from https://www.lfd.uci.edu/~gohlke/pythonlibs/ and install it from that +folder with the command 'pip install python_ldap-3.1.0-cp37-cp37m-win_amd64.whl' + +9. copy build_web2py.py, web2py.win.spec and web2py.win_no_console.spec from this folder to C:\web2py\ +10. (only for python 2) - due to a PyInstaller bug, you need to manually change the file gluon\rocket.py, line 26, from IS_JYTHON += platform.system() == 'Java' to IS_JYTHON = False +11. (optional, for having a full working interactive shell) change the fake site.py module included within the PyInstaller installation +with the content of the files web2py.site_37.py or web2py.site_27.py from this folder - see comments inside these files for details +12. open a CMD and go to C:\web2py. Run: + + python build_web2py.py + +If everything goes fine, you'll obtain the 64 bit binary build zipped as C:\web2py\web2py_win.zip. +If you try to run it in a 32 bit Windows system, you'll correctly get a 'web2py.exe not a valid Win32 application' error message. + +## Gothca: +- at least on Windows 7, you can get an error stating that "api-ms-win-crt-runtime-l1-1-0.dll is missing". You can easily resolve it by +installing "Visual C++ Redistributable for Visual Studio" described earlier From 64c66000faae0a3bbc81b46e159f286d24698bdc Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Mon, 1 Jul 2019 22:50:37 +0200 Subject: [PATCH 03/35] Modified fake site.py from PyInstaller - for PY2 --- extras/build_web2py/web2py.site_27.py | 1980 +++++++++++++++++++++++++ 1 file changed, 1980 insertions(+) create mode 100644 extras/build_web2py/web2py.site_27.py diff --git a/extras/build_web2py/web2py.site_27.py b/extras/build_web2py/web2py.site_27.py new file mode 100644 index 00000000..0724da50 --- /dev/null +++ b/extras/build_web2py/web2py.site_27.py @@ -0,0 +1,1980 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + web2py-pyinstaller/web2py.site_27.py at master · nicozanf/web2py-pyinstaller + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + +
+ +
+ + +
+ +
+ + + +
+
+
+ + + + + + + + + + +
+
+ +
    + + + + +
  • + +
    + +
    + + + Unwatch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • + + + Fork + + +
  • +
+ +

+ + /web2py-pyinstaller + + +

+ +
+ + + + + + +
+
+
+ + + + + + + Permalink + + + + +
+ + +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+
+ + +
+ + Find file + + + Copy path + +
+
+ + + + +
+ Fetching contributors… +
+ +
+ + Cannot retrieve contributors at this time +
+
+ + + + +
+ +
+ +
+ 202 lines (163 sloc) + + 6.03 KB +
+ +
+ +
+ Raw + Blame + History +
+ + +
+ + + + +
+ +
+
+ +
+
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
"""
web2py.site_27.py
Source:
This is the 3.4 PyInstaller's fake site.py
(see https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/fake-modules/site.py)
with the addition of the original 2.7 cpython code (see https://github.com/python/cpython/blob/2.7/Lib/site.py )
and adapted for reducing the size of the resulting frozen code
Purpose:
having back additional commands (mainly help and quit) in the python shell
Usage:
after installing PyInstaller, rename this file to site.py and overwrite the existing PyInstaller one;
on Windows 10: C:/Python27/Lib/site-packages/PyInstaller/fake-modules/site.py
on Mac: /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PyInstaller/fake-modules/site.py
"""
+
+
+
#-----------------------------------------------------------------------------
# Copyright (c) 2013-2018, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
+
+
"""
This is a fake 'site' module available in default Python Library.
The real 'site' does some magic to find paths to other possible
Python modules. We do not want this behaviour for frozen applications.
Fake 'site' makes PyInstaller to work with distutils and to work inside
virtualenv environment.
"""
+
# Marker to be used in our test-suite.
__pyinstaller__faked__site__module__ = True
+
# TODO test the following code stub from real 'site' module.
+
+
# Prefixes for site-packages; add additional prefixes like /usr/local here
PREFIXES = []
+
# Enable per user site-packages directory
# set it to False to disable the feature or True to force the feature
ENABLE_USER_SITE = False
+
+
# For distutils.commands.install
# These values are initialized by the getuserbase() and getusersitepackages()
# functions, through the main() function when Python starts.
# Issue #1699: Freezing pip requires 'site.USER_SITE' to be a 'str' not None.
USER_SITE = ''
USER_BASE = None
+
+
#
# The following has been borrowed from https://github.com/python/cpython/blob/2.7/Lib/site.py
# and adapted for reducing the size of the frozen code
#
+
import os
import sys
import __builtin__
+
def setquit():
"""Define new builtins 'quit' and 'exit'.
These are objects which make the interpreter exit when called.
The repr of each object contains a hint at how it works.
"""
if os.sep == ':':
eof = 'Cmd-Q'
elif os.sep == '\\':
eof = 'Ctrl-Z plus Return'
else:
eof = 'Ctrl-D (i.e. EOF)'
+
class Quitter(object):
def __init__(self, name):
self.name = name
def __repr__(self):
return 'Use %s() or %s to exit' % (self.name, eof)
def __call__(self, code=None):
# Shells like IDLE catch the SystemExit, but listen when their
# stdin wrapper is closed.
try:
sys.stdin.close()
except:
pass
raise SystemExit(code)
__builtin__.quit = Quitter('quit')
__builtin__.exit = Quitter('exit')
+
+
class _Printer(object):
"""interactive prompt objects for printing the license text, a list of
contributors and the copyright notice."""
+
MAXLINES = 23
+
def __init__(self, name, data, files=(), dirs=()):
self.__name = name
self.__data = data
self.__files = files
self.__dirs = dirs
self.__lines = None
+
def __setup(self):
if self.__lines:
return
data = None
for dir in self.__dirs:
for filename in self.__files:
filename = os.path.join(dir, filename)
try:
fp = file(filename, "rU")
data = fp.read()
fp.close()
break
except IOError:
pass
if data:
break
if not data:
data = self.__data
self.__lines = data.split('\n')
self.__linecnt = len(self.__lines)
+
def __repr__(self):
self.__setup()
if len(self.__lines) <= self.MAXLINES:
return "\n".join(self.__lines)
else:
return "Type %s() to see the full %s text" % ((self.__name,)*2)
+
def __call__(self):
self.__setup()
prompt = 'Hit Return for more, or q (and Return) to quit: '
lineno = 0
while 1:
try:
for i in range(lineno, lineno + self.MAXLINES):
print self.__lines[i]
except IndexError:
break
else:
lineno += self.MAXLINES
key = None
while key is None:
key = raw_input(prompt)
if key not in ('', 'q'):
key = None
if key == 'q':
break
+
def setcopyright():
"""Set 'copyright' and 'credits' in __builtin__"""
__builtin__.copyright = _Printer("copyright", sys.copyright)
__builtin__.credits = _Printer("credits", """\
Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
for supporting Python development. See www.python.org for more information.""")
here = os.path.dirname(os.__file__)
__builtin__.license = _Printer(
"license", "See https://www.python.org/psf/license/",
["LICENSE.txt", "LICENSE"],
[os.path.join(here, os.pardir), here, os.curdir])
+
+
class _Helper(object):
"""Define the builtin 'help'.
This is a wrapper around pydoc.help (with a twist).
"""
+
def __repr__(self):
return "Type help() for interactive help, " \
"or help(object) for help about object."
def __call__(self, *args, **kwds):
import pydoc
return pydoc.help(*args, **kwds)
+
def sethelper():
__builtin__.help = _Helper()
+
def main():
"""Add standard site-specific directories to the module search path.
This function is called automatically when this module is imported,
unless the python interpreter was started with the -S flag.
"""
setquit()
setcopyright()
sethelper()
+
+
main()
+ + + +
+ +
+ + + +
+ + +
+ + +
+
+ + + + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + + + + + + +
+ + + + From ab257031b5bd33041f6cfea59dcd5e680e341988 Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Mon, 1 Jul 2019 22:51:25 +0200 Subject: [PATCH 04/35] Modified fake site.py from PyInstaller - for PY3 --- extras/build_web2py/web2py.site_37.py | 1653 +++++++++++++++++++++++++ 1 file changed, 1653 insertions(+) create mode 100644 extras/build_web2py/web2py.site_37.py diff --git a/extras/build_web2py/web2py.site_37.py b/extras/build_web2py/web2py.site_37.py new file mode 100644 index 00000000..be35bdea --- /dev/null +++ b/extras/build_web2py/web2py.site_37.py @@ -0,0 +1,1653 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + web2py-pyinstaller/web2py.site_37.py at master · nicozanf/web2py-pyinstaller + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ Skip to content +
+ + + + + + + + + + +
+ +
+ + +
+ +
+ + + +
+
+
+ + + + + + + + + + +
+
+ +
    + + + + +
  • + +
    + +
    + + + Unwatch + + +
    + Notifications +
    +
    + + + + + + + +
    +
    +
    + +
    +
  • + +
  • +
    +
    + + +
    +
    + + +
    + +
  • + +
  • + + + Fork + + +
  • +
+ +

+ + /web2py-pyinstaller + + +

+ +
+ + + + + + +
+
+
+ + + + + + + Permalink + + + + +
+ + +
+ + Branch: + master + + + + + + + +
+ +
+ + Find file + + + Copy path + +
+
+ + +
+ + Find file + + + Copy path + +
+
+ + + + +
+ Fetching contributors… +
+ +
+ + Cannot retrieve contributors at this time +
+
+ + + + +
+ +
+ +
+ 121 lines (89 sloc) + + 3.8 KB +
+ +
+ +
+ Raw + Blame + History +
+ + +
+ + + + +
+ +
+
+ +
+
+
+ + + + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
"""
web2py.site_37.py
Source:
This is the 3.4 PyInstaller's fake site.py
(see https://github.com/pyinstaller/pyinstaller/blob/develop/PyInstaller/fake-modules/site.py)
with the addition of the original 3.7 cpython code (see https://github.com/python/cpython/blob/3.7/Lib/site.py )
and adapted for reducing the size of the resulting frozen code
Purpose:
having back additional commands (mainly help and quit) in the python shell
Usage:
after installing PyInstaller, rename this file to site.py and overwrite the existing PyInstaller one;
on Windows 10: C:/users/my_name/AppData/Local/Programs/Python/Python37/Lib/site-packages/PyInstaller/fake-modules/site.py
on Mac: /Library/Frameworks/Python.framework/Versions/3.7/lib/python3.7/site-packages/PyInstaller/fake-modules/site.py
"""
+
+
+
#-----------------------------------------------------------------------------
# Copyright (c) 2013-2018, PyInstaller Development Team.
#
# Distributed under the terms of the GNU General Public License with exception
# for distributing bootloader.
#
# The full license is in the file COPYING.txt, distributed with this software.
#-----------------------------------------------------------------------------
+
+
"""
This is a fake 'site' module available in default Python Library.
The real 'site' does some magic to find paths to other possible
Python modules. We do not want this behaviour for frozen applications.
Fake 'site' makes PyInstaller to work with distutils and to work inside
virtualenv environment.
"""
+
# Marker to be used in our test-suite.
__pyinstaller__faked__site__module__ = True
+
# TODO test the following code stub from real 'site' module.
+
+
# Prefixes for site-packages; add additional prefixes like /usr/local here
PREFIXES = []
+
# Enable per user site-packages directory
# set it to False to disable the feature or True to force the feature
ENABLE_USER_SITE = False
+
+
# For distutils.commands.install
# These values are initialized by the getuserbase() and getusersitepackages()
# functions, through the main() function when Python starts.
# Issue #1699: Freezing pip requires 'site.USER_SITE' to be a 'str' not None.
USER_SITE = ''
USER_BASE = None
+
+
#
# The following has been borrowed from https://github.com/python/cpython/blob/3.7/Lib/site.py
# and adapted for reducing the size of the frozen code
#
+
import os
import sys
import builtins
import _sitebuiltins
+
+
def setquit():
"""Define new builtins 'quit' and 'exit'.
These are objects which make the interpreter exit when called.
The repr of each object contains a hint at how it works.
"""
if os.sep == '\\':
eof = 'Ctrl-Z plus Return'
else:
eof = 'Ctrl-D (i.e. EOF)'
+
builtins.quit = _sitebuiltins.Quitter('quit', eof)
builtins.exit = _sitebuiltins.Quitter('exit', eof)
+
+
def setcopyright():
"""Set 'copyright' and 'credits' in builtins"""
builtins.copyright = _sitebuiltins._Printer("copyright", sys.copyright)
if sys.platform[:4] == 'java':
builtins.credits = _sitebuiltins._Printer(
"credits",
"Jython is maintained by the Jython developers (www.jython.org).")
else:
builtins.credits = _sitebuiltins._Printer("credits", """\
Thanks to CWI, CNRI, BeOpen.com, Zope Corporation and a cast of thousands
for supporting Python development. See www.python.org for more information.""")
files, dirs = [], []
builtins.license = _sitebuiltins._Printer(
"license",
"See https://www.python.org/psf/license/",
files, dirs)
+
+
def sethelper():
builtins.help = _sitebuiltins._Helper()
+
def main():
"""Add standard site-specific directories to the module search path.
This function is called automatically when this module is imported,
unless the python interpreter was started with the -S flag.
"""
setquit()
setcopyright()
sethelper()
+
+
main()
+ + + +
+ +
+ + + +
+ + +
+ + +
+
+ + + + + +
+ +
+ +
+
+ + +
+ + + + + + +
+ + + You can’t perform that action at this time. +
+ + + + + + + + + + + + + + +
+ + + + From 6fddca4e4f959c81734f402d1bbce3f1b289936e Mon Sep 17 00:00:00 2001 From: Dinis Date: Wed, 17 Jul 2019 15:18:44 +0100 Subject: [PATCH 05/35] Force page reload with anchors Force page to reload even when the location contains anchors, while using "web2py-redirect-location". Otherwise, when the location is the same and the url has an anchor it won't redirect. --- applications/admin/static/js/web2py.js | 1 + 1 file changed, 1 insertion(+) diff --git a/applications/admin/static/js/web2py.js b/applications/admin/static/js/web2py.js index 22b9f253..b4c0a5d3 100644 --- a/applications/admin/static/js/web2py.js +++ b/applications/admin/static/js/web2py.js @@ -284,6 +284,7 @@ var redirect = xhr.getResponseHeader('web2py-redirect-location'); if (redirect !== null) { window.location = redirect; + window.location.reload(); // Force reload even with anchors } /* run this here only if this Ajax request is NOT for a web2py component. */ if (xhr.getResponseHeader('web2py-component-content') === null) { From a23a068d40b14ffe84efa054b55e1fe5b73faba4 Mon Sep 17 00:00:00 2001 From: jvanbraekel <29703119+jvanbraekel@users.noreply.github.com> Date: Tue, 23 Jul 2019 15:52:21 +0200 Subject: [PATCH 06/35] Add utf-8 encoding in latex log opening By default, open use ascii encoding leading to crash when non ascii caracters are present . Fix it by enforcing UTF-8 encoding --- gluon/contrib/markmin/markmin2pdf.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/contrib/markmin/markmin2pdf.py b/gluon/contrib/markmin/markmin2pdf.py index 7e3c2eec..299cb1dc 100644 --- a/gluon/contrib/markmin/markmin2pdf.py +++ b/gluon/contrib/markmin/markmin2pdf.py @@ -80,7 +80,7 @@ def latex2pdf(latex, pdflatex='pdflatex', passes=3): outfile.close() re_errors = re.compile('^\!(.*)$', re.M) re_warnings = re.compile('^LaTeX Warning\:(.*)$', re.M) - flog = open(logname) + flog = open(logname,encoding="utf-8") try: loglines = flog.read() finally: From 251314ceb89ed63c6fd7a84f76071d26432bf8da Mon Sep 17 00:00:00 2001 From: jvanbraekel <29703119+jvanbraekel@users.noreply.github.com> Date: Wed, 24 Jul 2019 09:43:03 +0200 Subject: [PATCH 07/35] Only return get_vars after a failing login Since the redirect is a GET action, there is no reason to return post vars from the failing attempt. --- gluon/tools.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/gluon/tools.py b/gluon/tools.py index aefebbc5..e6421b88 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -2638,9 +2638,7 @@ class Auth(AuthAPI): # invalid login session.flash = specific_error if self.settings.login_specify_error else self.messages.invalid_login callback(onfail, None) - if 'password' in request.post_vars: - del request.post_vars['password'] - redirect(self.url(args=request.args, vars=request.vars),client_side=settings.client_side) + redirect(self.url(args=request.args, vars=request.get_vars),client_side=settings.client_side) else: # use a central authentication server cas = settings.login_form From 37d1fca32c9ab5571ef29401405d0f479f413a11 Mon Sep 17 00:00:00 2001 From: jvanbraekel <29703119+jvanbraekel@users.noreply.github.com> Date: Thu, 25 Jul 2019 11:28:37 +0200 Subject: [PATCH 08/35] Enable greek symbols support Pakage was missing form the template, leading to errors when greeks characters were used --- gluon/contrib/markmin/markmin2latex.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gluon/contrib/markmin/markmin2latex.py b/gluon/contrib/markmin/markmin2latex.py index 8f37e8bb..643e83d5 100755 --- a/gluon/contrib/markmin/markmin2latex.py +++ b/gluon/contrib/markmin/markmin2latex.py @@ -237,6 +237,7 @@ WRAPPER = """ \\usepackage{graphicx} \\usepackage{grffile} \\usepackage[utf8x]{inputenc} +\\usepackage{textgreek} \\definecolor{lg}{rgb}{0.9,0.9,0.9} \\definecolor{dg}{rgb}{0.3,0.3,0.3} \\def\\ft{\\small\\tt} From b4c2ee830429a8c1e2f14d3612e4671f6b40233b Mon Sep 17 00:00:00 2001 From: Dinis Date: Thu, 25 Jul 2019 17:15:19 +0100 Subject: [PATCH 09/35] Allow easily switching fake_migrate on to allow easier fixes of the database migrations --- gluon/console.py | 6 ++++++ gluon/shell.py | 4 +++- gluon/widget.py | 3 ++- scripts/migrator.py | 4 +++- 4 files changed, 14 insertions(+), 3 deletions(-) diff --git a/gluon/console.py b/gluon/console.py index 624941a7..10cf5a23 100644 --- a/gluon/console.py +++ b/gluon/console.py @@ -266,6 +266,12 @@ web2py will attempt to run a GUI to ask for it when starting the web server '(default is %(default)s), see -S above. NOTE: when the APP_ENV ' 'argument of -S include a controller c automatic import of ' 'models is always enabled') + g.add_argument('--fake_migrate', + default=False, + action='store_true', + help= + 'force DAL to fake migrate all tables; ' + 'monkeypatch in the DAL class to force _fake_migrate=True') g.add_argument('--force_migrate', '--force-migrate', default=False, action='store_true', help= diff --git a/gluon/shell.py b/gluon/shell.py index f8de2abd..f249c341 100644 --- a/gluon/shell.py +++ b/gluon/shell.py @@ -217,7 +217,8 @@ def run( python_code=None, cron_job=False, scheduler_job=False, - force_migrate=False): + force_migrate=False, + fake_migrate=False): """ Start interactive shell or run Python script (startfile) in web2py controller environment. appname is formatted like: @@ -255,6 +256,7 @@ def run( def custom_init(*args, **kwargs): kwargs['migrate_enabled'] = True kwargs['migrate'] = True + kwargs['fake_migrate'] = fake_migrate logger.info('Forcing migrate_enabled=True') orig_init(*args, **kwargs) diff --git a/gluon/widget.py b/gluon/widget.py index b41974ff..98d6791d 100644 --- a/gluon/widget.py +++ b/gluon/widget.py @@ -741,7 +741,8 @@ def start(): sys.argv = [options.run or ''] + options.args run(options.shell, plain=options.plain, bpython=options.bpython, import_models=options.import_models, startfile=options.run, - cron_job=options.cron_job, force_migrate=options.force_migrate) + cron_job=options.cron_job, force_migrate=options.force_migrate, + fake_migrate=options.fake_migrate) return # set size of cron thread pools diff --git a/scripts/migrator.py b/scripts/migrator.py index d94c5fa6..6f9c9a65 100644 --- a/scripts/migrator.py +++ b/scripts/migrator.py @@ -1,6 +1,7 @@ # -*- coding: utf-8 -*- ''' To use, e.g. python .\web2py.py -S APPNAME --force_migrate +To use, e.g. python .\web2py.py -S APPNAME --force_migrate --fake_migrate ''' import logging @@ -31,5 +32,6 @@ for db_name in databases: for table_name in tables: # Force migration of lazy tables logger.debug("Ensuring migration of table '%s'", table_name) - db(db[table_name]).isempty() + table = db[table_name] + db(table).isempty() db.commit() From 019295e1d15ba6d0110b3fb1519c6f763fa956a0 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 11 Aug 2019 10:58:22 -0700 Subject: [PATCH 10/35] reverting 2c364c2079c4c12cbb861ba6b9153a44b748eb14 which incorrecly assumes the scheme can only be http or https --- gluon/packages/dal | 2 +- gluon/rewrite.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/packages/dal b/gluon/packages/dal index 54191338..8e544905 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 541913385cb731f2802b3f1b6f744093bb3abdf3 +Subproject commit 8e544905d3304c587f52cdedd3948cf586c4f7ae diff --git a/gluon/rewrite.py b/gluon/rewrite.py index 48c1535b..526e2a10 100644 --- a/gluon/rewrite.py +++ b/gluon/rewrite.py @@ -204,7 +204,7 @@ def url_out(request, environ, application, controller, function, if host is True or (host is None and (scheme or port is not None)): host = request.env.http_host if not scheme or scheme is True: - scheme = 'https' if request and request.is_https else 'http' + scheme = request.env.get('wsgi_url_scheme', 'http').lower() if request else 'http' if host: host_port = host if not port else host.split(':', 1)[0] + ':%s' % port url = '%s://%s%s' % (scheme, host_port, url) From 179edb659a14f97c7ceb6f5d28219daf9d4a969d Mon Sep 17 00:00:00 2001 From: Dinis Date: Tue, 13 Aug 2019 18:04:30 +0100 Subject: [PATCH 11/35] Load all models when using --force_migrate (same behaviour as appadmin). --- gluon/shell.py | 1 + 1 file changed, 1 insertion(+) diff --git a/gluon/shell.py b/gluon/shell.py index f249c341..fe94692c 100644 --- a/gluon/shell.py +++ b/gluon/shell.py @@ -249,6 +249,7 @@ def run( fileutils.create_app(adir) if force_migrate: + c = 'appadmin' # Load all models (hack already used for appadmin controller) import_models = True from gluon.dal import DAL orig_init = DAL.__init__ From 8b55025cb333396b4cdb22ca7d0dbed3a5506a6a Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sat, 17 Aug 2019 22:46:31 -0700 Subject: [PATCH 12/35] serializing decimal as float, thanks villas --- gluon/packages/dal | 2 +- gluon/serializers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/packages/dal b/gluon/packages/dal index 8e544905..32871a9c 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 8e544905d3304c587f52cdedd3948cf586c4f7ae +Subproject commit 32871a9c1572e4917702f9eb82db72518bc6a7d9 diff --git a/gluon/serializers.py b/gluon/serializers.py index a72bc216..a1064ebc 100644 --- a/gluon/serializers.py +++ b/gluon/serializers.py @@ -82,7 +82,7 @@ def custom_json(o): elif isinstance(o, integer_types): return int(o) elif isinstance(o, decimal.Decimal): - return str(o) + return float(o) elif isinstance(o, (bytes, bytearray)): return str(o) elif isinstance(o, lazyT): From 4a838c2c145031b06622c6d155383c46ed0352c9 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sat, 17 Aug 2019 23:43:25 -0700 Subject: [PATCH 13/35] biopic web2py tests --- .travis.yml | 12 +++++------- gluon/packages/dal | 2 +- 2 files changed, 6 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 83b3d7f7..94c7a13a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,24 +4,22 @@ sudo: required cache: pip -dist: "xenial" +dist: "bionic"" services: - mysql python: - '2.7' - - '3.5' - '3.6' - - '3.6-dev' - '3.7' - - '3.7-dev' - - 'pypy3.5' + - '3.8-dev' + - 'pypy3.6-beta' matrix: allow_failures: - - python: '3.6-dev' - - python: '3.7-dev' + - python: '3.8-dev' + - python: 'pypy3.6-beta' install: - pip install -e . diff --git a/gluon/packages/dal b/gluon/packages/dal index 32871a9c..18e3baff 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 32871a9c1572e4917702f9eb82db72518bc6a7d9 +Subproject commit 18e3baff77e4fc231d1665d295da4b2626eb281e From af151783c62cbfd0577fa6696b245cbf84adc571 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 18 Aug 2019 00:20:24 -0700 Subject: [PATCH 14/35] test --- .travis.yml | 10 +++------- gluon/packages/dal | 2 +- 2 files changed, 4 insertions(+), 8 deletions(-) diff --git a/.travis.yml b/.travis.yml index 94c7a13a..094f0de0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,10 +1,8 @@ language: python sudo: required - cache: pip - -dist: "bionic"" +dist: "bionic" services: - mysql @@ -13,13 +11,11 @@ python: - '2.7' - '3.6' - '3.7' - - '3.8-dev' - - 'pypy3.6-beta' + - 'pypy3.5' matrix: allow_failures: - - python: '3.8-dev' - - python: 'pypy3.6-beta' + - python: 'pypy3.5' install: - pip install -e . diff --git a/gluon/packages/dal b/gluon/packages/dal index 18e3baff..0e873575 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 18e3baff77e4fc231d1665d295da4b2626eb281e +Subproject commit 0e8735751b7c86206dbcda5cb41330cedfa8a061 From 12d1ca739d9d31b39bde82985439001ceefe5578 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 18 Aug 2019 00:21:31 -0700 Subject: [PATCH 15/35] reverting test 3.5 --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 094f0de0..c54e8800 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,6 +9,7 @@ services: python: - '2.7' + - '3.5' - '3.6' - '3.7' - 'pypy3.5' From 529444cda7f6538ab39ff50b6210b080f4d1eddb Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 18 Aug 2019 00:47:25 -0700 Subject: [PATCH 16/35] fixed a test for Decimal serializer --- gluon/packages/dal | 2 +- gluon/tests/test_serializers.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/packages/dal b/gluon/packages/dal index 0e873575..bf208124 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 0e8735751b7c86206dbcda5cb41330cedfa8a061 +Subproject commit bf2081247d1d1ac6cdf656de841bfe0fa0dd1155 diff --git a/gluon/tests/test_serializers.py b/gluon/tests/test_serializers.py index d3c2cb48..6c7d8a41 100644 --- a/gluon/tests/test_serializers.py +++ b/gluon/tests/test_serializers.py @@ -44,7 +44,7 @@ class TestSerializers(unittest.TestCase): # self.assertEqual(json(1), json(1)) # decimal stringified obj = {'a': decimal.Decimal('4.312312312312')} - self.assertEqual(json(obj), u'{"a": "4.312312312312"}') + self.assertEqual(json(obj), u'{"a": 4.312312312312}') # lazyT translated T = TranslatorFactory('', 'en') lazy_translation = T('abc') From b7202df0b9f5a18e54ec0967c2d2e1b297391591 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 18 Aug 2019 01:11:04 -0700 Subject: [PATCH 17/35] do not test 3.5 on bionic --- .travis.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index c54e8800..094f0de0 100644 --- a/.travis.yml +++ b/.travis.yml @@ -9,7 +9,6 @@ services: python: - '2.7' - - '3.5' - '3.6' - '3.7' - 'pypy3.5' From 75491fb2734994435a5c145204cdcf790b3a1e3f Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Fri, 23 Aug 2019 12:25:11 +0100 Subject: [PATCH 18/35] python3 compatibility for JSONRPCError Trying this again, now that I learned about gluon._compat --- gluon/contrib/simplejsonrpc.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/contrib/simplejsonrpc.py b/gluon/contrib/simplejsonrpc.py index 0ffe8add..2769b09d 100644 --- a/gluon/contrib/simplejsonrpc.py +++ b/gluon/contrib/simplejsonrpc.py @@ -30,7 +30,7 @@ else: from io import StringIO import random import json - +from gluon._compat import basestring class JSONRPCError(RuntimeError): "Error object for remote procedure call fail" From 1dec1b4358d271815a0fa8fbba8d466b1a9010f1 Mon Sep 17 00:00:00 2001 From: Mirko Galimberti Date: Mon, 2 Sep 2019 13:50:39 +0200 Subject: [PATCH 19/35] Checks for user availability before accessing the registration key --- gluon/tools.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/tools.py b/gluon/tools.py index e6421b88..a6d79678 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -3171,12 +3171,12 @@ class Auth(AuthAPI): formname='retrieve_password', dbio=False, onvalidation=onvalidation, hideerror=self.settings.hideerror): user = table_user(email=form.vars.email) - key = user.registration_key if not user: current.session.flash = \ self.messages.invalid_email redirect(self.url(args=request.args)) - elif key in ('pending', 'disabled', 'blocked') or (key or '').startswith('pending'): + key = user.registration_key + if key in ('pending', 'disabled', 'blocked') or (key or '').startswith('pending'): current.session.flash = \ self.messages.registration_pending redirect(self.url(args=request.args)) From d17572fb105b5a1aafb7c03aad8b87aeb9b7b016 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Thu, 5 Sep 2019 00:02:19 -0700 Subject: [PATCH 20/35] Don't set form in trap_form as ajax_page element --- applications/welcome/static/js/web2py.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/welcome/static/js/web2py.js b/applications/welcome/static/js/web2py.js index 22b9f253..8eaf54aa 100644 --- a/applications/welcome/static/js/web2py.js +++ b/applications/welcome/static/js/web2py.js @@ -335,7 +335,7 @@ } else { formData = form.serialize(); // Fallback for older browsers. } - web2py.ajax_page('post', url, formData, target, form); + web2py.ajax_page('post', url, formData, target); e.preventDefault(); }); From 0f638f9cdf62832b01c62c4c2bcbb8e326906392 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 9 Sep 2019 21:13:01 -0700 Subject: [PATCH 21/35] possibly fixed the Redis problem, thanks Rastafarian --- gluon/contrib/redis_session.py | 6 +++--- gluon/globals.py | 8 ++++---- gluon/packages/dal | 2 +- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/gluon/contrib/redis_session.py b/gluon/contrib/redis_session.py index 8639f496..4ea11442 100644 --- a/gluon/contrib/redis_session.py +++ b/gluon/contrib/redis_session.py @@ -13,7 +13,7 @@ from gluon import current from gluon.storage import Storage from gluon.contrib.redis_utils import acquire_lock, release_lock from gluon.contrib.redis_utils import register_release_lock -from gluon._compat import to_bytes +from gluon._compat import to_native logger = logging.getLogger("web2py.session.redis") @@ -182,11 +182,11 @@ class MockQuery(object): key = self.keyprefix + ':' + str(self.value) if self.with_lock: acquire_lock(self.db.r_server, key + ':lock', self.value, 2) - rtn = self.db.r_server.hgetall(key) + rtn = {to_native(k.decode): v for k, v in self.db.r_server.hgetall(key).items()} if rtn: if self.unique_key: # make sure the id and unique_key are correct - if rtn['unique_key'] == self.unique_key: + if rtn['unique_key'] == to_native(self.unique_key): rtn['update_record'] = self.update # update record support else: rtn = None diff --git a/gluon/globals.py b/gluon/globals.py index a3b95d31..43276e44 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -13,7 +13,7 @@ Contains the classes for the global used variables: """ from gluon._compat import pickle, StringIO, copyreg, Cookie, urlparse, PY2, iteritems, to_unicode, to_native, \ - to_bytes, unicodeT, long, hashlib_md5, urllib_quote + to_bytes, unicodeT, long, hashlib_md5, urllib_quote, to_native from gluon.storage import Storage, List from gluon.streamer import streamer, stream_file_or_304_or_206, DEFAULT_CHUNK_SIZE from gluon.contenttype import contenttype @@ -1055,7 +1055,7 @@ class Session(Storage): if record_id.isdigit() and long(record_id) > 0: new_unique_key = web2py_uuid() row = table(record_id) - if row and row['unique_key'] == unique_key: + if row and to_native(row['unique_key']) == to_native(unique_key): table._db(table.id == record_id).update(unique_key=new_unique_key) else: record_id = None @@ -1231,9 +1231,9 @@ class Session(Storage): session_pickled = response.session_pickled or pickle.dumps(self, pickle.HIGHEST_PROTOCOL) - dd = dict(locked=False, + dd = dict(locked=0, client_ip=response.session_client, - modified_datetime=request.now, + modified_datetime=request.now.isostring(), session_data=session_pickled, unique_key=unique_key) if record_id: diff --git a/gluon/packages/dal b/gluon/packages/dal index bf208124..8e2305ed 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit bf2081247d1d1ac6cdf656de841bfe0fa0dd1155 +Subproject commit 8e2305ed3efb923130389e0fd92393d471234ea2 From 89c392d224befaaf0331b1937ae06f9216688854 Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Tue, 17 Sep 2019 14:48:15 +0100 Subject: [PATCH 22/35] correcting indentation --- gluon/contrib/login_methods/saml2_auth.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gluon/contrib/login_methods/saml2_auth.py b/gluon/contrib/login_methods/saml2_auth.py index a791f0d3..0e454992 100644 --- a/gluon/contrib/login_methods/saml2_auth.py +++ b/gluon/contrib/login_methods/saml2_auth.py @@ -150,14 +150,14 @@ class Saml2Auth(object): self.config_file = config_file self.maps = maps - # URL for redirecting users to when they sign out + # URL for redirecting users to when they sign out self.saml_logout_url = logout_url # URL to let users change their password in the IDP system self.saml_change_password_url = change_password_url - # URL to specify an IDP if using federation metadata or an MDQ - self.entityid = entityid + # URL to specify an IDP if using federation metadata or an MDQ + self.entityid = entityid def login_url(self, next="/"): d = saml2_handler(current.session, current.request, entityid=self.entityid) From 2b30157ccea0d12de02b43c4a6a2f33e4ad43304 Mon Sep 17 00:00:00 2001 From: Tim Nyborg Date: Wed, 25 Sep 2019 11:06:23 +0100 Subject: [PATCH 23/35] Update redis_cache.py moving logging as well --- gluon/contrib/redis_cache.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/gluon/contrib/redis_cache.py b/gluon/contrib/redis_cache.py index 3b92eef0..87437af7 100644 --- a/gluon/contrib/redis_cache.py +++ b/gluon/contrib/redis_cache.py @@ -208,12 +208,12 @@ class RedisClient(object): def retry_call(self, key, f, time_expire, with_lock): self.RETRIES += 1 - if self.RETRIES <= self.MAX_RETRIES: - logger.error("sleeping %s seconds before reconnecting" % (2 * self.RETRIES)) - time.sleep(2 * self.RETRIES) + if self.RETRIES <= self.MAX_RETRIES: if self.fail_gracefully: self.RETRIES = 0 return f() + logger.error("sleeping %s seconds before reconnecting" % (2 * self.RETRIES)) + time.sleep(2 * self.RETRIES) return self.__call__(key, f, time_expire, with_lock) else: self.RETRIES = 0 From c95b4e43d72ad504c80b4f7f1c9a7da5b77e37f6 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Mon, 30 Sep 2019 20:47:06 -0700 Subject: [PATCH 24/35] isostring->isoformat --- gluon/globals.py | 2 +- gluon/packages/dal | 2 +- gluon/packages/yatl | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/gluon/globals.py b/gluon/globals.py index 43276e44..59a2f2d4 100644 --- a/gluon/globals.py +++ b/gluon/globals.py @@ -1233,7 +1233,7 @@ class Session(Storage): dd = dict(locked=0, client_ip=response.session_client, - modified_datetime=request.now.isostring(), + modified_datetime=request.now.isoformat(), session_data=session_pickled, unique_key=unique_key) if record_id: diff --git a/gluon/packages/dal b/gluon/packages/dal index 8e2305ed..74c4a1c8 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 8e2305ed3efb923130389e0fd92393d471234ea2 +Subproject commit 74c4a1c832770f15de06d8ac9edd0d47c579bc6c diff --git a/gluon/packages/yatl b/gluon/packages/yatl index 2eb050b8..468c093a 160000 --- a/gluon/packages/yatl +++ b/gluon/packages/yatl @@ -1 +1 @@ -Subproject commit 2eb050b8e251813e905ecbabba839ca578901a3a +Subproject commit 468c093ab094a274f200cc9a94b338e1687bce41 From e4845aeef6b13c8173f155d8692a818c7f0e4ba5 Mon Sep 17 00:00:00 2001 From: jicho Date: Wed, 9 Oct 2019 09:33:18 +0200 Subject: [PATCH 25/35] No redirect when url ends with # When a redirect url ends with a hash (#) the browser (Chrome) does not redirect/refreshes the browser. This is happening with this setting: ``` form = SQLFORM.grid( query, client_side_delete=True ) ``` --- applications/welcome/static/js/web2py.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/applications/welcome/static/js/web2py.js b/applications/welcome/static/js/web2py.js index 8eaf54aa..e526a306 100644 --- a/applications/welcome/static/js/web2py.js +++ b/applications/welcome/static/js/web2py.js @@ -283,7 +283,11 @@ doc.ajaxSuccess(function (e, xhr) { var redirect = xhr.getResponseHeader('web2py-redirect-location'); if (redirect !== null) { - window.location = redirect; + if (!redirect.endsWith('#')) { + window.location.href = redirect; + } else { + window.location.reload(); + } } /* run this here only if this Ajax request is NOT for a web2py component. */ if (xhr.getResponseHeader('web2py-component-content') === null) { From 5bcf34aba512440d181347598dd79c179d4bc9a8 Mon Sep 17 00:00:00 2001 From: Queen Vinyl Darkscratch Date: Tue, 15 Oct 2019 16:32:43 -0700 Subject: [PATCH 26/35] Add events for form upload progress --- applications/welcome/static/js/web2py.js | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/applications/welcome/static/js/web2py.js b/applications/welcome/static/js/web2py.js index 8eaf54aa..80138930 100644 --- a/applications/welcome/static/js/web2py.js +++ b/applications/welcome/static/js/web2py.js @@ -367,6 +367,24 @@ 'data': data, 'processData': !isFormData, 'contentType': contentType, + 'xhr': function() { + var xhr = new window.XMLHttpRequest(); + + xhr.upload.addEventListener("progress", function(evt) { + if (evt.lengthComputable) { + var percentComplete = evt.loaded / evt.total; + percentComplete = parseInt(percentComplete * 100); + web2py.fire(element, 'w2p:uploadProgress', [percentComplete], target); + + if (percentComplete === 100) { + web2py.fire(element, 'w2p:uploadComplete', [], target); + } + + } + }, false); + + return xhr; + }, 'beforeSend': function (xhr, settings) { xhr.setRequestHeader('web2py-component-location', document.location); xhr.setRequestHeader('web2py-component-element', target); From dce5fbb4720127132b10ae7ea780e298b0250d88 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 20 Oct 2019 21:43:01 -0700 Subject: [PATCH 27/35] fixed validate maybe --- gluon/packages/dal | 2 +- gluon/tools.py | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/packages/dal b/gluon/packages/dal index 74c4a1c8..a16c0046 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 74c4a1c832770f15de06d8ac9edd0d47c579bc6c +Subproject commit a16c0046bff21ab48e306811828cc021c8ebaeb6 diff --git a/gluon/tools.py b/gluon/tools.py index a6d79678..61db6e2a 100644 --- a/gluon/tools.py +++ b/gluon/tools.py @@ -2301,7 +2301,7 @@ class Auth(AuthAPI): # in this case they will have to reset their password to login if fields.get(settings.passfield): fields[settings.passfield] = \ - settings.table_user[settings.passfield].validate(fields[settings.passfield])[0] + settings.table_user[settings.passfield].validate(fields[settings.passfield], None)[0] if not fields.get(settings.userfield): raise ValueError('register_bare: userfield not provided or invalid') user = self.get_or_create_user(fields, login=False, get=False, From cf91145db0b62caaf16135bc2d5b9a90c37c707b Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 20 Oct 2019 21:48:49 -0700 Subject: [PATCH 28/35] made validators compliant with new dal --- gluon/scheduler.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/scheduler.py b/gluon/scheduler.py index 4ca449c1..3510dfb9 100644 --- a/gluon/scheduler.py +++ b/gluon/scheduler.py @@ -530,7 +530,7 @@ class IS_CRONLINE(object): def __init__(self, error_message=None): self.error_message = error_message - def __call__(self, value): + def __call__(self, value, record_id=None): recur = CronParser(value, datetime.datetime.now()) try: recur.next() @@ -550,7 +550,7 @@ class TYPE(object): self.myclass = myclass self.parse = parse - def __call__(self, value): + def __call__(self, value, record_id=None): from gluon import current try: obj = loads(value) From 8f989944236cc8912efdbc10e7ac05886e2c7bc1 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sun, 20 Oct 2019 22:04:11 -0700 Subject: [PATCH 29/35] fixed validate for good --- gluon/authapi.py | 2 +- gluon/packages/dal | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/authapi.py b/gluon/authapi.py index 220ba437..7c2ac20f 100644 --- a/gluon/authapi.py +++ b/gluon/authapi.py @@ -803,7 +803,7 @@ class AuthAPI(object): # Finally verify the password passfield = settings.password_field - password = table_user[passfield].validate(kwargs.get(passfield, ''))[0] + password = table_user[passfield].validate(kwargs.get(passfield, ''), None)[0] if password == user[passfield]: self.login_user(user) diff --git a/gluon/packages/dal b/gluon/packages/dal index a16c0046..67c9760f 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit a16c0046bff21ab48e306811828cc021c8ebaeb6 +Subproject commit 67c9760f71612dc376c5bded9b677b5f212b4968 From f7b3abdc89d579214d1201f7b16262ff21ce2117 Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Tue, 22 Oct 2019 21:54:01 +0200 Subject: [PATCH 30/35] Fix broken inframe Vimeo video It fixes Issue #2068 --- applications/examples/views/default/documentation.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/examples/views/default/documentation.html b/applications/examples/views/default/documentation.html index d29ab1a9..d94ddc34 100644 --- a/applications/examples/views/default/documentation.html +++ b/applications/examples/views/default/documentation.html @@ -3,7 +3,7 @@
{{=get_content('main')}}
- +
{{=get_content('official')}} {{=get_content('community')}} From 92bb2c22418168a8077c785459946e58c262538c Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Wed, 23 Oct 2019 22:05:12 +0200 Subject: [PATCH 31/35] Added Python 3 binaries to the download page --- .../examples/views/default/download.html | 41 ++++++++++++++----- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/applications/examples/views/default/download.html b/applications/examples/views/default/download.html index d8df3871..9abe6856 100644 --- a/applications/examples/views/default/download.html +++ b/applications/examples/views/default/download.html @@ -9,7 +9,8 @@ - + + @@ -17,10 +18,13 @@ + + + - + @@ -48,7 +60,8 @@ +
For Normal UsersFor Normal Users (Py3)For Legacy Users (Py2) For Testers For Developers
- For Windows + Windows binaries - For Windows + Windows binaries + + Windows binaries Git Repository @@ -28,17 +32,25 @@
- For Mac + Mac binaries - For Mac + Mac binaries + + Mac binaries + + Manual
Source Code + Source Code + Source Code
- Manual + Change Log @@ -62,13 +75,19 @@

- The source code version works on Windows and most Unix systems, including Linux, BSD and Mac . It requires Python 2.6 (no more supported), Python 2.7 (stable) or Python 3.5+ (recommended for new projects) already installed on your system. - There are also binary packages for Windows and Mac OS X. They include the Python 2.7 interpreter so you do not need to have it pre-installed. + The source code version works on Windows and most Unix systems, including Linux, BSD and Mac . It requires Python 3.5+ (recommended for new projects) + or Python 2.7+ (stable, for use with legacy apps) already installed on your system. +

+

+ There are also binary packages for Windows and MacOs. They include the Python interpreter version 3.7.4 or 2.7.16, so you do not need to have it pre-installed.

Instructions

-

With the binary packages, after download, just unzip it and then click on web2py.exe (windows) or web2py.app (osx). - If you prefer to run it from source with your own Python interpreter alreay installed, type:

+

With the binary packages, after download, just unzip it and then click on web2py.exe (Windows) or web2py (MacOs).

+

Note that on recent MacOs versions (10.12+) you could face problems in running the binary App program, due to the last changes to the security settings. +In this case, press the 'control' key + click on downloaded file and then 'open' it (confirm the warnings). Finally move the program in Applications and run it from there. +

+

If you prefer to run it from source with your own Python interpreter alreay installed, type:

{{=CODE("python web2py.py", language=None, counter='>', _class='boxCode')}}

or for more info type:

{{=CODE("python web2py.py -h", language=None, counter='>', _class='boxCode')}} From 77bcda3f3ed35b1944cf6bdaa054081fa99f7edc Mon Sep 17 00:00:00 2001 From: Nico Zanferrari Date: Wed, 23 Oct 2019 22:41:19 +0200 Subject: [PATCH 32/35] Added Python 3 binaries to the download page +typo It fixes issue #2027. ** IMPORTANT ** - before approving, you need to copy from https://github.com/nicozanf/web2py-pyinstaller to https://mdipierro.pythonanywhere.com/examples/static the files: - web2py_win.zip - web2py_win_py2.zip - web2py_osx.zip - web2py_osx_py2.zip And also modify the procedures for the "For Testers" versions on https://mdipierro.pythonanywhere.com/examples/static, that should use the previous ones as binaries. --- applications/examples/views/default/download.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/applications/examples/views/default/download.html b/applications/examples/views/default/download.html index 9abe6856..dbed6375 100644 --- a/applications/examples/views/default/download.html +++ b/applications/examples/views/default/download.html @@ -87,7 +87,7 @@

Note that on recent MacOs versions (10.12+) you could face problems in running the binary App program, due to the last changes to the security settings. In this case, press the 'control' key + click on downloaded file and then 'open' it (confirm the warnings). Finally move the program in Applications and run it from there.

-

If you prefer to run it from source with your own Python interpreter alreay installed, type:

+

If you prefer to run it from source with your own Python interpreter already installed, type:

{{=CODE("python web2py.py", language=None, counter='>', _class='boxCode')}}

or for more info type:

{{=CODE("python web2py.py -h", language=None, counter='>', _class='boxCode')}} From 7038758960c5bf79e609329cdf709b65f1924517 Mon Sep 17 00:00:00 2001 From: Bernhard Miklautz Date: Thu, 24 Oct 2019 15:24:59 +0200 Subject: [PATCH 33/35] new [scheduler]: add parameter use_spawn Add a new parameter to Scheduler to allow it to use spawn multiprocessing method. This is only available with python3 therefore the parameter is ignored with python2. --- gluon/scheduler.py | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/gluon/scheduler.py b/gluon/scheduler.py index 3510dfb9..75e75c74 100644 --- a/gluon/scheduler.py +++ b/gluon/scheduler.py @@ -596,12 +596,12 @@ class Scheduler(threading.Thread): utc_time(bool): do all datetime calculations assuming UTC as the timezone. Remember to pass `start_time` and `stop_time` to tasks accordingly - + use_spawn(bool): use spawn for subprocess (only useable with python3) """ def __init__(self, db, tasks=None, migrate=True, worker_name=None, group_names=None, heartbeat=HEARTBEAT, - max_empty_runs=0, discard_results=False, utc_time=False): + max_empty_runs=0, discard_results=False, utc_time=False, use_spawn=False): threading.Thread.__init__(self) self.setDaemon(True) @@ -639,6 +639,7 @@ class Scheduler(threading.Thread): current._scheduler = self self.define_tables(db, migrate=migrate) + self.use_spawn = use_spawn def execute(self, task): """Start the background process. @@ -649,10 +650,19 @@ class Scheduler(threading.Thread): Returns: a `TaskReport` object """ - outq = multiprocessing.Queue() - retq = multiprocessing.Queue(maxsize=1) - self.process = p = \ - multiprocessing.Process(target=executor, args=(retq, task, outq)) + outq = None + retq = None + if (self.use_spawn and not PY2): + ctx = multiprocessing.get_context('spawn') + outq = ctx.Queue() + retq = ctx.Queue(maxsize=1) + sel.process = p = ctx.Process(target=executor, args=(retq, task, outq)) + else: + outq = multiprocessing.Queue() + retq = multiprocessing.Queue(maxsize=1) + self.process = p = \ + multiprocessing.Process(target=executor, args=(retq, task, outq)) + self.process_queues = (retq, outq) logger.debug(' task starting') From a0eac8fce7781441b626f113e6e52fb97cb2eedf Mon Sep 17 00:00:00 2001 From: Mateusz Mojsiejuk Date: Fri, 25 Oct 2019 15:52:11 +0200 Subject: [PATCH 34/35] Add support for freeIPA ldap auth --- gluon/contrib/login_methods/freeipa_auth.py | 59 +++++++++++++++++++++ 1 file changed, 59 insertions(+) create mode 100644 gluon/contrib/login_methods/freeipa_auth.py diff --git a/gluon/contrib/login_methods/freeipa_auth.py b/gluon/contrib/login_methods/freeipa_auth.py new file mode 100644 index 00000000..f068fefb --- /dev/null +++ b/gluon/contrib/login_methods/freeipa_auth.py @@ -0,0 +1,59 @@ +import sys +import logging + +try: + import ldap + + ldap.set_option(ldap.OPT_X_TLS_REQUIRE_CERT, ldap.OPT_X_TLS_NEVER) +except Exception as detail: + logging.error('missing ldap, try "pip install python-ldap"') + raise detail + + +def freeipa_auth(server, basedn, group): + """ + custom module for freeIPA auth in web2py + server: freeipa ip + base_dn: root of ldap tree containing user & groups + group: group authing user has to be a member of + + """ + logger = logging.getLogger("web2py.auth.freeipa_auth") + + def freeipa_auth_aux(username, password): + if password == "" or username == "": + logger.warning("blank username / password not allowed") + return False + + bind_user_base = "uid=" + username + ",cn=users," + basedn + ldap_filter = "memberof=cn=" + group + ",cn=groups," + basedn + + session = ldap.initialize("ldaps://" + server + ":636") + try: + session.bind_s(bind_user_base, password) + except ldap.LDAPError: + import traceback + + logger.warning("[%s] Error in ldap bind" % str(username)) + logger.debug(traceback.format_exc()) + return False + + try: + result = session.search_s( + bind_user_base, ldap.SCOPE_SUBTREE, ldap_filter, ["member"] + ) + session.unbind() + except ldap.LDAPError as detail: + logger.warning( + "ldap_auth: searc %s for %s resulted in %s: %s\n" + % (bind_user_base, ldap_filter, exc_type, exc_value) + ) + + try: + if result == list(): + return False + return True + except: + return False + + return freeipa_auth_aux From eda8277fbdb779852f3383244b191429f0eb2a34 Mon Sep 17 00:00:00 2001 From: mdipierro Date: Sat, 2 Nov 2019 20:09:47 -0700 Subject: [PATCH 35/35] removed unwanted import that breaks python3.8 --- gluon/compileapp.py | 2 +- gluon/languages.py | 1 - gluon/packages/dal | 2 +- 3 files changed, 2 insertions(+), 3 deletions(-) diff --git a/gluon/compileapp.py b/gluon/compileapp.py index cbc41518..43b2c220 100644 --- a/gluon/compileapp.py +++ b/gluon/compileapp.py @@ -565,7 +565,7 @@ def run_models_in(environment): TEST_CODE = r""" def _TEST(): - import doctest, sys, cStringIO, types, cgi, gluon.fileutils + import doctest, sys, cStringIO, types, gluon.fileutils if not gluon.fileutils.check_credentials(request): raise HTTP(401, web2py_error='invalid credentials') stdout = sys.stdout diff --git a/gluon/languages.py b/gluon/languages.py index 9ed60f9c..4ad2ac95 100644 --- a/gluon/languages.py +++ b/gluon/languages.py @@ -16,7 +16,6 @@ import re import sys import pkgutil import logging -from cgi import escape from threading import RLock from pydal._compat import copyreg, PY2, maketrans, iterkeys, unicodeT, to_unicode, to_bytes, iteritems, to_native, pjoin diff --git a/gluon/packages/dal b/gluon/packages/dal index 67c9760f..e595b921 160000 --- a/gluon/packages/dal +++ b/gluon/packages/dal @@ -1 +1 @@ -Subproject commit 67c9760f71612dc376c5bded9b677b5f212b4968 +Subproject commit e595b921b02173bb804a061faa6d54773f18cd81