more regex improvements, thanks Paolo Pastori

This commit is contained in:
mdipierro
2019-05-12 19:39:33 -07:00
parent 0372c50ef5
commit 95bbaf6a38
3 changed files with 69 additions and 45 deletions
+7 -11
View File
@@ -166,9 +166,9 @@ def check_version():
new_version, version = check_new_version(request.env.web2py_version, new_version, version = check_new_version(request.env.web2py_version,
WEB2PY_VERSION_URL) WEB2PY_VERSION_URL)
if new_version == -1: if new_version in (-1, -2):
return A(T('Unable to check for upgrades'), _href=WEB2PY_URL) return A(T('Unable to check for upgrades'), _href=WEB2PY_URL)
elif new_version != True: elif not new_version:
return A(T('web2py is up to date'), _href=WEB2PY_URL) return A(T('web2py is up to date'), _href=WEB2PY_URL)
elif platform.system().lower() in ('windows', 'win32', 'win64') and os.path.exists("web2py.exe"): elif platform.system().lower() in ('windows', 'win32', 'win64') and os.path.exists("web2py.exe"):
return SPAN('You should upgrade to %s' % version.split('(')[0]) return SPAN('You should upgrade to %s' % version.split('(')[0])
@@ -1082,9 +1082,6 @@ def about():
return dict(app=app, about=MARKMIN(about), license=MARKMIN(license), progress=report_progress(app)) return dict(app=app, about=MARKMIN(about), license=MARKMIN(license), progress=report_progress(app))
regex_include = r"""(?P<all>\{\{\s*include\s+['"](?P<name>[^'"]*)['"]\s*\}\})"""
regex_extend = r"""^\s*(?P<all>\{\{\s*extend\s+['"](?P<name>[^'"]+)['"]\s*\}\})"""
def design(): def design():
""" Application design handler """ """ Application design handler """
app = get_app() app = get_app()
@@ -1121,10 +1118,9 @@ def design():
models = listdir(apath('%s/models/' % app, r=request), '.*\.py$') models = listdir(apath('%s/models/' % app, r=request), '.*\.py$')
models = [x.replace('\\', '/') for x in models] models = [x.replace('\\', '/') for x in models]
defines = {} defines = {}
regex_tables = r"""^[\w]+\.define_table\(\s*['"](?P<name>\w+)['"]"""
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_tables, data, re.MULTILINE) defines[m] = re.findall(REGEX_DEFINE_TABLE, data, re.MULTILINE)
defines[m].sort() defines[m].sort()
# Get all controllers # Get all controllers
@@ -1148,12 +1144,12 @@ def design():
include = {} include = {}
for c in views: for c in views:
data = safe_read(apath('%s/views/%s' % (app, c), r=request)) data = safe_read(apath('%s/views/%s' % (app, c), r=request))
items = re.findall(regex_extend, data, re.MULTILINE) items = re.findall(REGEX_EXTEND, data, re.MULTILINE)
if items: if items:
extend[c] = items[0][1] extend[c] = items[0][1]
items = re.findall(regex_include, data) items = re.findall(REGEX_INCLUDE, data)
include[c] = [i[1] for i in items] include[c] = [i[1] for i in items]
# Get all modules # Get all modules
@@ -1289,11 +1285,11 @@ def plugin():
include = {} include = {}
for c in views: for c in views:
data = safe_read(apath('%s/views/%s' % (app, c), r=request)) data = safe_read(apath('%s/views/%s' % (app, c), r=request))
items = re.findall(regex_extend, data, re.MULTILINE) items = re.findall(REGEX_EXTEND, data, re.MULTILINE)
if items: if items:
extend[c] = items[0][1] extend[c] = items[0][1]
items = re.findall(regex_include, data) items = re.findall(REGEX_INCLUDE, data)
include[c] = [i[1] for i in items] include[c] = [i[1] for i in items]
# Get all modules # Get all modules
+56 -29
View File
@@ -1,5 +1,5 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
# vim: set ts=4 sw=4 et ai:
""" """
| This file is part of the web2py Web Framework | This file is part of the web2py Web Framework
@@ -10,24 +10,34 @@ Utility functions for the Admin application
------------------------------------------- -------------------------------------------
""" """
from __future__ import print_function
import os import os
import sys
import traceback import traceback
import zipfile
from shutil import rmtree, copyfileobj from shutil import rmtree, copyfileobj
import zipfile
import sys
from gluon.fileutils import (w2p_pack, create_app, w2p_unpack, from gluon.fileutils import (w2p_pack, create_app, w2p_unpack,
w2p_pack_plugin, w2p_unpack_plugin, w2p_pack_plugin, w2p_unpack_plugin,
up, fix_newlines, abspath, recursive_unlink, up, fix_newlines, abspath, recursive_unlink,
read_file, write_file, parse_version) read_file, write_file, parse_version, missing_app_folders)
from gluon.restricted import RestrictedError from gluon.restricted import RestrictedError
from gluon.settings import global_settings from gluon.settings import global_settings
from gluon.cache import CacheOnDisk from gluon.cache import CacheOnDisk
from gluon._compat import urlopen, to_native from gluon._compat import urlopen, to_native
# TODO: move into add_path_first
if not global_settings.web2py_runtime_gae: if not global_settings.web2py_runtime_gae:
import site import site
REGEX_DEFINE_TABLE = r"""^\w+\.define_table\(\s*['"](?P<name>\w+)['"]"""
REGEX_EXTEND = r"""^\s*(?P<all>\{\{\s*extend\s+['"](?P<name>[^'"]+)['"]\s*\}\})"""
REGEX_INCLUDE = r"""(?P<all>\{\{\s*include\s+['"](?P<name>[^'"]+)['"]\s*\}\})"""
# TODO: swap arguments, let first ('r' or whatever) be mandatory
def apath(path='', r=None): def apath(path='', r=None):
"""Builds a path inside an application folder """Builds a path inside an application folder
@@ -38,8 +48,9 @@ def apath(path='', r=None):
""" """
opath = up(r.folder) opath = up(r.folder)
while path[:3] == '../': while path.startswith('../'):
(opath, path) = (up(opath), path[3:]) opath = up(opath)
path = path[3:]
return os.path.join(opath, path).replace('\\', '/') return os.path.join(opath, path).replace('\\', '/')
@@ -81,7 +92,7 @@ def app_pack_compiled(app, request, raise_ex=False):
filename = apath('../deposit/%s.w2p' % app, request) filename = apath('../deposit/%s.w2p' % app, request)
w2p_pack(filename, apath(app, request), compiled=True) w2p_pack(filename, apath(app, request), compiled=True)
return filename return filename
except Exception as e: except Exception:
if raise_ex: if raise_ex:
raise raise
return None return None
@@ -105,7 +116,7 @@ def app_cleanup(app, request):
if os.path.exists(path): if os.path.exists(path):
for f in os.listdir(path): for f in os.listdir(path):
try: try:
if f[:1] != '.': if not f.startswith('.'):
os.unlink(os.path.join(path, f)) os.unlink(os.path.join(path, f))
except IOError: except IOError:
r = False r = False
@@ -115,7 +126,7 @@ def app_cleanup(app, request):
if os.path.exists(path): if os.path.exists(path):
for f in os.listdir(path): for f in os.listdir(path):
try: try:
if f[:1] != '.': if not f.startswith('.'):
recursive_unlink(os.path.join(path, f)) recursive_unlink(os.path.join(path, f))
except (OSError, IOError): except (OSError, IOError):
r = False r = False
@@ -126,7 +137,7 @@ def app_cleanup(app, request):
CacheOnDisk(folder=path).clear() CacheOnDisk(folder=path).clear()
for f in os.listdir(path): for f in os.listdir(path):
try: try:
if f[:1] != '.': if not f.startswith('.'):
recursive_unlink(os.path.join(path, f)) recursive_unlink(os.path.join(path, f))
except (OSError, IOError): except (OSError, IOError):
r = False r = False
@@ -211,9 +222,9 @@ def app_install(app, fobj, request, filename, overwrite=None):
""" """
did_mkdir = False did_mkdir = False
if filename[-4:] == '.w2p': if filename.endswith('.w2p'):
extension = 'w2p' extension = 'w2p'
elif filename[-7:] == '.tar.gz': elif filename.endswith('.tar.gz'):
extension = 'tar.gz' extension = 'tar.gz'
else: else:
extension = 'tar' extension = 'tar'
@@ -300,7 +311,8 @@ def plugin_install(app, fobj, request, filename):
upname = apath('../deposit/%s' % filename, request) upname = apath('../deposit/%s' % filename, request)
try: try:
write_file(upname, fobj.read(), 'wb') with open(upname, 'wb') as appfp:
copyfileobj(fobj, appfp, 4194304) # 4 MB buffer
path = apath(app, request) path = apath(app, request)
w2p_unpack_plugin(upname, path) w2p_unpack_plugin(upname, path)
fix_newlines(path) fix_newlines(path)
@@ -322,7 +334,9 @@ def check_new_version(myversion, version_url):
tuple: state, version tuple: state, version
- state : `True` if upgrade available, `False` if current - state : `True` if upgrade available, `False` if current
version is up-to-date, -1 on error version is up-to-date, -1 on error,
-2 when the system is likely to be offline (no
internet link available)
- version : the most up-to-version available - version : the most up-to-version available
""" """
@@ -330,10 +344,19 @@ def check_new_version(myversion, version_url):
version = to_native(urlopen(version_url).read()) version = to_native(urlopen(version_url).read())
pversion = parse_version(version) pversion = parse_version(version)
pmyversion = parse_version(myversion) pmyversion = parse_version(myversion)
except IOError: except IOError as e:
import traceback from socket import gaierror
print(traceback.format_exc()) if isinstance(getattr(e, 'reason', None), gaierror) and \
return -1, myversion e.reason.errno == -2:
# assuming the version_url is ok the socket.gaierror
# (gaierror stands for getaddrinfo() error) that
# originates the exception is probably due to a
# missing internet link (i.e. the system is offline)
print('system is offline, cannot retrieve latest web2py version')
return -2, myversion
else:
print(traceback.format_exc())
return -1, myversion
if pversion[:3]+pversion[-6:] > pmyversion[:3]+pmyversion[-6:]: if pversion[:3]+pversion[-6:] > pmyversion[:3]+pmyversion[-6:]:
return True, version return True, version
@@ -360,7 +383,7 @@ def unzip(filename, dir, subfolder=''):
for name in sorted(zf.namelist()): for name in sorted(zf.namelist()):
if not name.startswith(subfolder): if not name.startswith(subfolder):
continue continue
# print name[n:] # print(name[n:])
if name.endswith('/'): if name.endswith('/'):
folder = os.path.join(dir, name[n:]) folder = os.path.join(dir, name[n:])
if not os.path.exists(folder): if not os.path.exists(folder):
@@ -421,6 +444,7 @@ def upgrade(request, url='http://web2py.com'):
return False, e return False, e
# TODO: move to fileutils
def add_path_first(path): def add_path_first(path):
sys.path = [path] + [p for p in sys.path if ( sys.path = [path] + [p for p in sys.path if (
not p == path and not p == (path + '/'))] not p == path and not p == (path + '/'))]
@@ -429,21 +453,24 @@ def add_path_first(path):
site.addsitedir(path) site.addsitedir(path)
# TODO: move to fileutils
def try_mkdir(path): def try_mkdir(path):
if not os.path.exists(path): if not os.path.exists(path):
try: try:
if os.path.islink(path): if os.path.islink(path):
# path is a broken link, try to mkdir the target of the link instead of the link itself. # path is a broken link, try to mkdir the target of the link
# instead of the link itself.
os.mkdir(os.path.realpath(path)) os.mkdir(os.path.realpath(path))
else: else:
os.mkdir(path) os.mkdir(path)
except OSError as e: except OSError as e:
if e.strerror == 'File exists': # In case of race condition. if e.errno == 17: # "File exists" (race condition).
pass pass
else: else:
raise e raise
# TODO: move to fileutils
def create_missing_folders(): def create_missing_folders():
if not global_settings.web2py_runtime_gae: if not global_settings.web2py_runtime_gae:
for path in ('applications', 'deposit', 'site-packages', 'logs'): for path in ('applications', 'deposit', 'site-packages', 'logs'):
@@ -453,16 +480,16 @@ def create_missing_folders():
paths = (global_settings.gluon_parent, abspath( paths = (global_settings.gluon_parent, abspath(
'site-packages', gluon=True), abspath('gluon', gluon=True), '') 'site-packages', gluon=True), abspath('gluon', gluon=True), '')
""" """
paths = (global_settings.gluon_parent, abspath( for p in (global_settings.gluon_parent,
'site-packages', gluon=True), '') abspath('site-packages', gluon=True),
[add_path_first(p) for p in paths] ''):
add_path_first(p)
# TODO: move to fileutils
def create_missing_app_folders(request): def create_missing_app_folders(request):
if not global_settings.web2py_runtime_gae: if not global_settings.web2py_runtime_gae:
if request.folder not in global_settings.app_folders: if request.folder not in global_settings.app_folders:
for subfolder in ('models', 'views', 'controllers', 'databases', for amf in missing_app_folders(request.folder):
'modules', 'cron', 'errors', 'sessions', try_mkdir(amf)
'languages', 'static', 'private', 'uploads'):
try_mkdir(os.path.join(request.folder, subfolder))
global_settings.app_folders.add(request.folder) global_settings.app_folders.add(request.folder)
+6 -5
View File
@@ -18,6 +18,7 @@ import time
import datetime import datetime
import logging import logging
import shutil import shutil
from gluon.http import HTTP from gluon.http import HTTP
from gzip import open as gzopen from gzip import open as gzopen
from gluon.recfile import generate from gluon.recfile import generate
@@ -254,13 +255,11 @@ def w2p_pack(filename, path, compiled=False, filenames=None):
os.unlink(tarname) os.unlink(tarname)
def create_missing_folders(path): def missing_app_folders(path):
for subfolder in ('models', 'views', 'controllers', 'databases', for subfolder in ('models', 'views', 'controllers', 'databases',
'modules', 'cron', 'errors', 'sessions', 'modules', 'cron', 'errors', 'sessions',
'languages', 'static', 'private', 'uploads'): 'languages', 'static', 'private', 'uploads'):
subpath = os.path.join(path, subfolder) yield os.path.join(path, subfolder)
if not os.path.exists(subpath):
os.mkdir(subpath)
def create_welcome_w2p(): def create_welcome_w2p():
@@ -269,7 +268,9 @@ def create_welcome_w2p():
logger = logging.getLogger("web2py") logger = logging.getLogger("web2py")
try: try:
app_path = 'applications/welcome' app_path = 'applications/welcome'
create_missing_folders(app_path) for amf in missing_app_folders(app_path):
if not os.path.exists(amf):
os.mkdir(amf)
w2p_pack('welcome.w2p', app_path) w2p_pack('welcome.w2p', app_path)
logger.info("New installation: created welcome.w2p file") logger.info("New installation: created welcome.w2p file")
except: except: