Compare commits

...

64 Commits

Author SHA1 Message Date
mdipierro f31c9002f7 reverted pydal 16.11 2017-03-21 00:42:02 -05:00
mdipierro 6354fbedf8 commented a test 2017-03-21 00:24:17 -05:00
mdipierro cc11a14ce3 commented a test 2017-03-21 00:21:21 -05:00
mdipierro 2fa9597cd8 added debug info 2017-03-21 00:04:55 -05:00
mdipierro c9d656ea45 added logging, thanks gi0baro 2017-03-20 18:06:23 -05:00
mdipierro 1eec01b830 pydal 17.03 2017-03-20 16:21:05 -05:00
mdipierro c10983b191 Merge branch 'master' of github.com:web2py/web2py 2017-03-20 16:15:31 -05:00
mdipierro 975ab7b923 SQLFORM.grid(showblobs=True) 2017-03-20 16:15:18 -05:00
mdipierro 16f60d5cff Merge pull request #1565 from kristjanvalur/master
Update compileapp.py
2017-01-30 12:48:37 -06:00
mdipierro 930370ee91 Merge pull request #1562 from richboss/dev_urandom
don't write to /dev/urandom on Windows platforms
2017-01-30 12:47:50 -06:00
mdipierro 215abc9e4f download over https for security 2017-01-30 12:46:50 -06:00
Kristján Valur Jónsson b6e5e16526 Update compileapp.py
The "current" may have been altered by the controller.  This is the case for admin/controllers/shell.py, in callback(), where a new shell environment is created (from gluon/shell)
If this happens, the incorrect "response" is being referenced and the output of the controller is lost.
2017-01-25 20:10:03 +00:00
Richard Boß b2548f5631 don't write to /dev/urandom on Windows platforms 2017-01-22 21:05:22 +01:00
mdipierro f14c384d83 Merge pull request #1558 from abastardi/fix-router
Fix router functions check
2017-01-19 09:23:16 -06:00
mdipierro 9f186e5d5d Merge pull request #1555 from maxslimmer/master
ccache page fix for disk cache statistics value
2017-01-19 09:23:02 -06:00
mdipierro 51dd427b9e Merge pull request #1550 from senolakkas/patch-2
fix css validation error
2017-01-19 09:22:38 -06:00
abastardi 7b3fe560ed Update test_router_functions to test extensions 2017-01-14 13:14:04 -05:00
abastardi bd526452a8 Fix router functions check
When the router checks whether the requested route matches a function in the
functions list, it does not strip the extension, causing failures for URLs with extensions.
This change strips the extension before comparing to the list of functions.
2017-01-13 15:52:42 -05:00
maxslimmer d862da3543 revert part of fix to displaying cache statistics (#1) 2017-01-04 18:08:57 -08:00
maxslimmer 0165cfadef get cache.disk statistics value for update and display 2017-01-04 18:03:37 -08:00
maxslimmer 46b7716b1d get cache.disk statistics for update 2017-01-04 18:02:23 -08:00
Şenol AKKAŞ 7e5277030a fix css validation error 2016-12-26 14:21:41 +03:00
mdipierro b2e03c9dee Merge pull request #1540 from ilvalle/fix_ipaddress
Replaced ipaddr with ipaddress.py (backported from py3)
2016-12-23 21:58:13 -06:00
mdipierro 0644df5283 Merge pull request #1549 from amerikan/patch-1
typo fix
2016-12-23 21:57:56 -06:00
Erik Montes 4acd9f8f2b typo fix 2016-12-21 11:17:12 -08:00
mdipierro ce0c5f2d5a Merge branch 'master' of github.com:web2py/web2py 2016-12-20 15:49:44 -06:00
mdipierro 28b0385d9b changes to fabfile 2016-12-20 15:49:30 -06:00
mdipierro ac9bccb9a2 Merge pull request #1548 from nextghost/languages
Include Auth and Crud messages in language file updates
2016-12-20 15:42:38 -06:00
mdipierro aa5b40528f Merge pull request #1546 from wish7code/master
Fix for #1443 - PR will enable emperor.uwsgi.service on boot
2016-12-20 15:42:10 -06:00
mdipierro 96efc7bfce Merge pull request #1539 from smorrison/master
when mkdir of missing app folders, handle broken links properly
2016-12-20 15:40:30 -06:00
mdipierro aa584faed6 Merge pull request #1538 from vinyldarkscratch/master
Add web2py componentBegin event
2016-12-20 15:39:55 -06:00
Martin Doucha e7cab3b975 Add Auth and Crud messages when updating language files 2016-12-20 18:54:20 +01:00
wish7 867f93b634 Fix for #1443 - currently emperor.uwsgi.service is not started on boot,
PR will enable emperor.uwsgi.service on boot
(behaviour as in old versions of this script)
2016-12-09 17:21:04 +01:00
mdipierro efff27ffe4 improved fabfile 2016-12-07 23:02:56 -06:00
ilvalle 637579f531 replaced ipaddr with ipaddress.py (backported from py3) 2016-12-03 08:42:35 +01:00
sean 52fe4407b8 when mkdir of missing app folders, handle broken links properly 2016-12-01 10:29:23 -05:00
Vinyl Darkscratch fc0add67b5 Add web2py componentBegin event
Like the “w2p:componentComplete” event I added a while back, this is
another event that I use in my website, and I thought it would be
helpful to share it with others.  This way, you can easily catch when a
web2py component starts loading, and write a handler for whatever
reason (in my case, determining when the user is navigating to a new
page through a smooth loading function piggybacking off of the web2py
component system)
2016-11-29 14:05:17 -08:00
Vinyl Darkscratch 3d2834c81a Merge remote-tracking branch 'web2py/master' 2016-11-29 13:57:46 -08:00
mdipierro 0b8ecea4dc sudo: required, thanks Leonel 2016-11-21 10:27:16 -06:00
mdipierro 67945c2d5c Merge pull request #1533 from gchiesa/casv3
implemented base support for CASv3
2016-11-21 09:13:41 -06:00
mdipierro c600854f4b Merge pull request #1532 from vinyldarkscratch/translations
Fix T.M() not adding to language files
2016-11-21 09:12:42 -06:00
Giuseppe Chiesa 2c70a858f1 implemented base support for CASv3 2016-11-17 13:30:11 +01:00
mdipierro ad9ebea900 Merge pull request #1531 from vinyldarkscratch/master
Mobile (iOS) flash dismissal fix
2016-11-14 08:34:00 -06:00
mdipierro c72330f2cd Merge pull request #1530 from BMarvi/master
Update extract_mysql_models.py
2016-11-14 08:33:30 -06:00
mdipierro 091d9c74b0 Merge pull request #1525 from michele-comitini/confirm_registration_redirect_fix
keep the _next while doing the redirect
2016-11-14 08:27:39 -06:00
mdipierro bebdbd9d5e Merge pull request #1519 from matclab/fix/1518
Allow for firstname and lastname in verify_email message
2016-11-14 08:27:10 -06:00
mdipierro 05e28ddffd Merge pull request #1516 from pixelbandito/grammar-uppercase-lowercase
Corrected use of 'lowercase' and 'uppercase' to fix #1515
2016-11-14 08:26:44 -06:00
Vinyl Darkscratch e19435dbcf Prevent Firefox from loading the page "javascript:null;" 2016-11-11 18:51:38 -08:00
Vinyl Darkscratch 90ee6f3754 Add three-quote support on markmin 2016-11-11 15:51:01 -08:00
Vinyl Darkscratch d51ea90e18 Code fix to allow adding markmin translations
Playing with this file made me realize that the quotes defining the
strings themselves are added to the regex searches, and that my
previous addition caused invalid syntax.  So, I decided to fix this by
placing the first quote before the markmin decorator.  (Triple quotes
won’t work, however…)
2016-11-11 15:49:28 -08:00
Vinyl Darkscratch 3fed558bdd Merge remote-tracking branch 'web2py/master' into translations 2016-11-11 15:44:21 -08:00
Vinyl Darkscratch 870d9d3e57 Fix .DS_Store ignore 2016-11-11 13:52:43 -08:00
Vinyl Darkscratch 0a07af55f9 Replace "#" link with "javascript:null;" 2016-11-11 03:31:10 -08:00
Vinyl Darkscratch f7adfbde76 Replace "#" link with "javascript:null;" 2016-11-11 03:30:50 -08:00
Vinyl Darkscratch 75c1d80824 Replace "#" link with "javascript:null;" 2016-11-11 03:30:16 -08:00
Marvi c64a9192d4 Update extract_mysql_models.py 2016-11-11 10:12:11 +01:00
Vinyl Darkscratch 8e79e49ae3 Mobile (iOS) fix for dismissing flashes
iOS devices don’t like listening to clicks on most objects.  They
typically prefer a and button objects.  This fix replaces the
#closeflash span with a link to “#” instead (while also inheriting
text-decoration and color styling), so that mobile (iOS) devices will
allow you to close the flash.
2016-11-10 01:19:06 -08:00
Vinyl Darkscratch 46ce04355f Merge remote-tracking branch 'web2py/master' 2016-11-10 01:14:40 -08:00
Michele Comitini 6b1225da02 keep the _next while doing the redirect 2016-11-04 09:59:49 +01:00
Michele Comitini 4ea31820aa Merge pull request #1520 from michele-comitini/wrong_serializers_import
fix wrong import in default controller of admin app
2016-11-03 12:00:15 +01:00
Michele Comitini 8e1630843a fix wrong import in default controller of admin app 2016-11-02 00:41:40 +01:00
Mathieu Clabaut 2d4817841f Allow for firstname and lastname in verify_email message 2016-11-01 11:31:01 +01:00
Chris Garcia 4226b6d0e1 Corrected use of 'lowercase' and 'uppercase' to fix #1515 2016-10-28 15:23:18 -05:00
Vinyl Darkscratch 3e2b8f89aa Merge remote-tracking branch 'web2py/master' into translations 2016-10-10 20:45:42 -07:00
33 changed files with 3387 additions and 2226 deletions
+1
View File
@@ -13,6 +13,7 @@
*.orig
Thumbs.db
.DS_Store
*.DS_Store
index.yaml
routes.py
logging.conf
+1 -1
View File
@@ -1,6 +1,6 @@
language: python
sudo: false
sudo: required
cache: pip
@@ -465,6 +465,7 @@ def ccache():
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
for key in cache.disk.storage:
value = cache.disk.storage[key]
if key == 'web2py_cache_statistics' and isinstance(value[1], dict):
disk['hits'] = value[1]['hit_total'] - value[1]['misses']
disk['misses'] = value[1]['misses']
+1 -1
View File
@@ -1960,7 +1960,7 @@ def git_push():
def plugins():
app = request.args(0)
from serializers import loads_json
from gluon.serializers import loads_json
if not session.plugins:
try:
rawlist = urlopen("http://www.web2pyslices.com/" +
+2 -2
View File
@@ -352,9 +352,9 @@
'modules': 'modules',
'Multi User Mode': 'Multi User Mode',
'Must include at least %s %s': 'Moet ten minste bevatten %s %s',
'Must include at least %s lower case': 'Moet ten minste bevatten %s lower case',
'Must include at least %s lowercase': 'Moet ten minste bevatten %s kleine letter',
'Must include at least %s of the following : %s': 'Moet ten minste bevatten %s van het volgende : %s',
'Must include at least %s upper case': 'Moet ten minste bevatten %s upper case',
'Must include at least %s uppercase': 'Moet ten minste bevatten %s hoofdletter',
'new application "%s" created': 'nieuwe applicatie "%s" gemaakt',
'new application "%s" imported': 'new application "%s" imported',
'New Application Wizard': 'Nieuwe Applicatie Wizard',
+2 -2
View File
@@ -356,9 +356,9 @@
'modules': 'модулі',
'Multi User Mode': 'Multi User Mode',
'Must include at least %s %s': 'Має вміщувати щонайменше %s %s',
'Must include at least %s lower case': 'Повинен включати щонайменше %s малих букв',
'Must include at least %s lowercase': 'Повинен включати щонайменше %s малих букв',
'Must include at least %s of the following : %s': 'Має включати не менше %s таких символів : %s',
'Must include at least %s upper case': 'Повинен включати щонайменше %s великих букв',
'Must include at least %s uppercase': 'Повинен включати щонайменше %s великих букв',
'new application "%s" created': 'новий додаток "%s" створено',
'new application "%s" imported': 'new application "%s" imported',
'New Application Wizard': 'Майстер створення нового додатку',
+3 -3
View File
@@ -314,8 +314,8 @@
// Vim does not support modifier only keys.
return false;
}
// TODO: Current bindings expect the character to be lower case, but
// it looks like vim key notation uses upper case.
// TODO: Current bindings expect the character to be lowercase, but
// it looks like vim key notation uses uppercase.
if (isUpperCase(lastPiece)) {
pieces[pieces.length - 1] = lastPiece.toLowerCase();
}
@@ -3644,7 +3644,7 @@
* Extract the regular expression from the query and return a Regexp object.
* Returns null if the query is blank.
* If ignoreCase is passed in, the Regexp object will have the 'i' flag set.
* If smartCase is passed in, and the query contains upper case letters,
* If smartCase is passed in, and the query contains uppercase letters,
* then ignoreCase is overridden, and the 'i' flag will not be set.
* If the query contains the /i in the flag part of the regular expression,
* then both ignoreCase and smartCase are ignored, and 'i' will be passed
File diff suppressed because it is too large Load Diff
+3 -1
View File
@@ -168,7 +168,8 @@
* and require no dom manipulations
*/
var doc = $(document);
doc.on('click', '.w2p_flash', function () {
doc.on('click', '.w2p_flash', function (event) {
event.preventDefault();
var t = $(this);
if (t.css('top') == '0px') t.slideUp('slow');
else t.fadeOut();
@@ -316,6 +317,7 @@
'beforeSend': function (xhr, settings) {
xhr.setRequestHeader('web2py-component-location', document.location);
xhr.setRequestHeader('web2py-component-element', target);
web2py.fire(element, 'w2p:componentBegin', [xhr, settings], target);
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
},
'success': function (data, status, xhr) {
@@ -465,6 +465,7 @@ def ccache():
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
for key in cache.disk.storage:
value = cache.disk.storage[key]
if key == 'web2py_cache_statistics' and isinstance(value[1], dict):
disk['hits'] = value[1]['hit_total'] - value[1]['misses']
disk['misses'] = value[1]['misses']
+3 -1
View File
@@ -168,7 +168,8 @@
* and require no dom manipulations
*/
var doc = $(document);
doc.on('click', '.w2p_flash', function () {
doc.on('click', '.w2p_flash', function (event) {
event.preventDefault();
var t = $(this);
if (t.css('top') == '0px') t.slideUp('slow');
else t.fadeOut();
@@ -316,6 +317,7 @@
'beforeSend': function (xhr, settings) {
xhr.setRequestHeader('web2py-component-location', document.location);
xhr.setRequestHeader('web2py-component-element', target);
web2py.fire(element, 'w2p:componentBegin', [xhr, settings], target);
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
},
'success': function (data, status, xhr) {
@@ -17,10 +17,10 @@
<tbody>
<tr>
<td>
<a class="btn btn180 rounded green" href="http://www.web2py.com/examples/static/web2py_win.zip">For Windows</a>
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_win.zip">For Windows</a>
</td>
<td>
<a class="btn btn180 rounded yellow" href="http://www.web2py.com/examples/static/nightly/web2py_win.zip">For Windows</a>
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_win.zip">For Windows</a>
</td>
<td>
<a class="btn btn180 rounded red" href="http://github.com/web2py/web2py/">Git Repository</a>
@@ -28,19 +28,19 @@
</tr>
<tr>
<td>
<a class="btn btn180 rounded green" href="http://www.web2py.com/examples/static/web2py_osx.zip">For Mac</a>
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_osx.zip">For Mac</a>
</td>
<td>
<a class="btn btn180 rounded yellow" href="http://www.web2py.com/examples/static/nightly/web2py_osx.zip">For Mac</a>
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_osx.zip">For Mac</a>
</td>
<td></td>
</tr>
<tr>
<td>
<a class="btn btn180 rounded green" href="http://www.web2py.com/examples/static/web2py_src.zip">Source Code</a>
<a class="btn btn180 rounded green" href="https://mdipierro.pythonanywhere.com/examples/static/web2py_src.zip">Source Code</a>
</td>
<td>
<a class="btn btn180 rounded yellow" href="http://www.web2py.com/examples/static/nightly/web2py_src.zip">Source Code</a>
<a class="btn btn180 rounded yellow" href="https://mdipierro.pythonanywhere.com/examples/static/nightly/web2py_src.zip">Source Code</a>
</td>
<td>
<a class="btn btn180 rounded red" href="http://web2py.readthedocs.org/en/latest/">Source code docs</a>
@@ -465,6 +465,7 @@ def ccache():
ram['keys'].append((key, GetInHMS(time.time() - value[0])))
for key in cache.disk.storage:
value = cache.disk.storage[key]
if key == 'web2py_cache_statistics' and isinstance(value[1], dict):
disk['hits'] = value[1]['hit_total'] - value[1]['misses']
disk['misses'] = value[1]['misses']
+3 -1
View File
@@ -168,7 +168,8 @@
* and require no dom manipulations
*/
var doc = $(document);
doc.on('click', '.w2p_flash', function () {
doc.on('click', '.w2p_flash', function (event) {
event.preventDefault();
var t = $(this);
if (t.css('top') == '0px') t.slideUp('slow');
else t.fadeOut();
@@ -316,6 +317,7 @@
'beforeSend': function (xhr, settings) {
xhr.setRequestHeader('web2py-component-location', document.location);
xhr.setRequestHeader('web2py-component-element', target);
web2py.fire(element, 'w2p:componentBegin', [xhr, settings], target);
return web2py.fire(element, 'ajax:beforeSend', [xhr, settings], target); //test a usecase, should stop here if returns false
},
'success': function (data, status, xhr) {
+2 -2
View File
@@ -7,7 +7,7 @@
# it is not safe to use as a generic.jsonp because of security implications.
if response.view == 'generic.jsonp':
raise HTTP(501,'generic.jsonp diasbled for security reasons')
raise HTTP(501,'generic.jsonp disabled for security reasons')
try:
from gluon.serializers import json
@@ -20,4 +20,4 @@ except ImportError:
raise HTTP(405, 'JSON not available')
except:
raise HTTP(405, 'JSON error')
}}
}}
Vendored
+3 -2
View File
@@ -1,7 +1,8 @@
from fabric.api import *
from fabric.operations import put, get
from fabric.contrib.files import exists
from fabric.contrib.files import exists, append, uncomment
import os
import crypt
import datetime
import getpass
@@ -19,11 +20,11 @@ def create_user(username):
"""fab -H root@host create_user:username"""
password = getpass.getpass('password for %s> ' % username)
run('useradd -m -G www-data -s /bin/bash -p %s %s' % (crypt.crypt(password, 'salt'), username))
local('ssh-copy-id %s' % env.hosts[0])
run('cp /etc/sudoers /tmp/sudoers.new')
append('/tmp/sudoers.new', '%s ALL=(ALL) NOPASSWD:ALL' % username, use_sudo=True)
run('visudo -c -f /tmp/sudoers.new')
run('EDITOR="cp /tmp/sudoers.new" visudo')
local('ssh-copy-id %s' % env.hosts[0])
uncomment('~%s/.bashrc' % username, '#force_color_prompt=yes')
def install_web2py():
+2
View File
@@ -32,6 +32,7 @@ if PY2:
import cgi
import cookielib
from xmlrpclib import ProtocolError
from gluon.contrib import ipaddress
BytesIO = StringIO
reduce = reduce
hashlib_md5 = hashlib.md5
@@ -97,6 +98,7 @@ else:
from http import cookiejar as cookielib
from xmlrpc.client import ProtocolError
import html # warning, this is the python3 module and not the web2py html module
import ipaddress
hashlib_md5 = lambda s: hashlib.md5(bytes(s, 'utf8'))
iterkeys = lambda d: iter(d.keys())
itervalues = lambda d: iter(d.values())
+5 -1
View File
@@ -438,7 +438,11 @@ def add_path_first(path):
def try_mkdir(path):
if not os.path.exists(path):
try:
os.mkdir(path)
if os.path.islink(path):
# path is a broken link, try to mkdir the target of the link instead of the link itself.
os.mkdir(os.path.realpath(path))
else:
os.mkdir(path)
except OSError as e:
if e.strerror == 'File exists': # In case of race condition.
pass
+1 -1
View File
@@ -640,7 +640,7 @@ def run_controller_in(controller, function, environment):
ccode = getcfs(layer, filename, lambda: compile2(code, layer))
restricted(ccode, environment, layer=filename)
response = current.response
response = environment["response"]
vars = response._vars
if response.postprocessing:
vars = reduce(lambda vars, p: p(vars), response.postprocessing, vars)
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+18 -10
View File
@@ -951,32 +951,40 @@ def findT(path, language=DEFAULT_LANGUAGE):
Note:
Must be run by the admin app
"""
from gluon.tools import Auth, Crud
lang_file = pjoin(path, 'languages', language + '.py')
sentences = read_dict(lang_file)
mp = pjoin(path, 'models')
cp = pjoin(path, 'controllers')
vp = pjoin(path, 'views')
mop = pjoin(path, 'modules')
def add_message(message):
if not message.startswith('#') and not '\n' in message:
tokens = message.rsplit('##', 1)
else:
# this allows markmin syntax in translations
tokens = [message]
if len(tokens) == 2:
message = tokens[0].strip() + '##' + tokens[1].strip()
if message and not message in sentences:
sentences[message] = message.replace("@markmin\x01", "")
for filename in \
listdir(mp, '^.+\.py$', 0) + listdir(cp, '^.+\.py$', 0)\
+ listdir(vp, '^.+\.html$', 0) + listdir(mop, '^.+\.py$', 0):
data = to_native(read_locked(filename))
items = regex_translate.findall(data)
items += ["@markmin\x01%s" %x for x in regex_translate_m.findall(data)]
for x in regex_translate_m.findall(data):
if x[0:3] in ["'''", '"""']: items.append("%s@markmin\x01%s" %(x[0:3], x[3:]))
else: items.append("%s@markmin\x01%s" %(x[0], x[1:]))
for item in items:
try:
message = safe_eval(item)
except:
continue # silently ignore inproperly formatted strings
if not message.startswith('#') and not '\n' in message:
tokens = message.rsplit('##', 1)
else:
# this allows markmin syntax in translations
tokens = [message]
if len(tokens) == 2:
message = tokens[0].strip() + '##' + tokens[1].strip()
if message and not message in sentences:
sentences[message] = message.replace("@markmin\x01", "")
add_message(message)
gluon_msg = [Auth.default_messages, Crud.default_messages]
for item in [x for m in gluon_msg for x in m.values() if x is not None]:
add_message(item)
if not '!langcode!' in sentences:
sentences['!langcode!'] = (
DEFAULT_LANGUAGE if language in ('default', DEFAULT_LANGUAGE) else language)
+1 -1
View File
@@ -1040,7 +1040,7 @@ class MapUrlIn(object):
else:
default_function = self.router.default_function # str or None
default_function = self.domain_function or default_function
if not arg0 or functions and arg0 not in functions:
if not arg0 or functions and arg0.split('.')[0] not in functions:
self.function = default_function or ""
self.pop_arg_if(arg0 and self.function == arg0)
else:
+6 -6
View File
@@ -2153,7 +2153,8 @@ class SQLFORM(FORM):
ignore_common_filters=None,
auto_pagination=True,
use_cursor=False,
represent_none=None):
represent_none=None,
showblobs=False):
formstyle = formstyle or current.response.formstyle
if isinstance(query, Set):
@@ -2194,7 +2195,7 @@ class SQLFORM(FORM):
buttondelete='icon trash icon-trash glyphicon glyphicon-trash',
buttonedit='icon pen icon-pencil glyphicon glyphicon-pencil',
buttontable='icon rightarrow icon-arrow-right glyphicon glyphicon-arrow-right',
buttonview='icon magnifier icon-zoom-in glyphicon glyphicon-zoom-in',
buttonview='icon magnifier icon-zoom-in glyphicon glyphicon-zoom-in'
)
elif not isinstance(ui, dict):
raise RuntimeError('SQLFORM.grid ui argument must be a dictionary')
@@ -2340,11 +2341,10 @@ class SQLFORM(FORM):
else:
fields = []
columns = []
filter1 = lambda f: isinstance(f, Field) and f.type != 'blob'
filter2 = lambda f: isinstance(f, Field) and f.readable
filter1 = lambda f: isinstance(f, Field) and f.readable and (f.type!='blob' or showblobs)
for table in tables:
fields += filter(filter1, table)
columns += filter(filter2, table)
columns += filter(filter1, table)
for k, f in iteritems(table):
if not k.startswith('_'):
if isinstance(f, Field.Virtual) and f.readable:
@@ -2862,7 +2862,7 @@ class SQLFORM(FORM):
for field in columns:
if not field.readable:
continue
if field.type == 'blob':
elif field.type == 'blob' and not showblobs:
continue
if isinstance(field, Field.Virtual) and field.tablename in row:
try:
+8 -4
View File
@@ -91,7 +91,8 @@ class TestAppAdmin(unittest.TestCase):
self.run_view()
self.run_view_file_stream()
except Exception as e:
print(e.message)
import traceback
print(traceback.format_exc())
self.fail('Could not make the view')
def test_index(self):
@@ -115,7 +116,8 @@ class TestAppAdmin(unittest.TestCase):
try:
self.run_view()
except Exception as e:
print(e.message)
import traceback
print(traceback.format_exc())
self.fail('Could not make the view')
def test_insert(self):
@@ -129,7 +131,8 @@ class TestAppAdmin(unittest.TestCase):
try:
self.run_view()
except Exception as e:
print(e.message)
import traceback
print(traceback.format_exc())
self.fail('Could not make the view')
def test_insert_submit(self):
@@ -151,7 +154,8 @@ class TestAppAdmin(unittest.TestCase):
try:
self.run_view()
except Exception as e:
print(e.message)
import traceback
print(traceback.format_exc())
self.fail('Could not make the view')
db = self.env['db']
lisa_record = db(db.auth_user.username == 'lisasimpson').select().first()
+45
View File
@@ -873,6 +873,27 @@ class TestRouter(unittest.TestCase):
self.assertEqual(str(URL(a='app2', c='default', f='index',
args=['ctr'])), "/app2/index/ctr")
# outbound - with extensions
self.assertEqual(
str(URL(a='app', c='default', f='index.json')), "/index.json")
self.assertEqual(
str(URL(a='app', c='default', f='index.json', args=['arg1'])), "/index.json/arg1")
self.assertEqual(str(
URL(a='app', c='default', f='user.json')), "/user.json")
self.assertEqual(str(
URL(a='app', c='default', f='user.json', args=['arg1'])), "/user.json/arg1")
self.assertEqual(str(URL(
a='app', c='default', f='user.json', args=['index'])), "/user.json/index")
self.assertEqual(str(
URL(a='app', c='default', f='index.json', args=['ctr'])), "/index.json/ctr")
self.assertEqual(
str(URL(a='app', c='ctr', f='ctrf1.json', args=['arg'])), "/ctr/ctrf1.json/arg")
self.assertEqual(str(URL(
a='app2', c='default', f='index.json', args=['arg1'])), "/app2/index.json/arg1")
self.assertEqual(str(URL(
a='app2', c='ctr', f='index.json', args=['arg1'])), "/app2/ctr/index.json/arg1")
# inbound
self.assertEqual(
filter_url('http://d.com/arg'), "/app/default/index ['arg']")
@@ -896,6 +917,30 @@ class TestRouter(unittest.TestCase):
self.assertEqual(
filter_url('http://d.com/app2/ctr/arg'), "/app2/ctr/arg")
# inbound - with extensions
self.assertEqual(
filter_url('http://d.com/index.json'), "/app/default/index.json")
self.assertEqual(filter_url('http://d.com/user.json'), "/app/default/user.json")
self.assertEqual(
filter_url('http://d.com/user.json/arg'), "/app/default/user.json ['arg']")
self.assertEqual(
filter_url('http://d.com/user.json/index'), "/app/default/user.json ['index']")
self.assertEqual(
filter_url('http://d.com/index.json/ctr'), "/app/default/index.json ['ctr']")
self.assertEqual(
filter_url('http://d.com/ctr/ctrf1.json/arg'), "/app/ctr/ctrf1.json ['arg']")
self.assertEqual(filter_url(
'http://d.com/app2/index.json/arg'), "/app2/default/index.json ['arg']")
self.assertEqual(
filter_url('http://d.com/app2/user.json'), "/app2/default/user.json")
self.assertEqual(filter_url(
'http://d.com/app2/user.json/arg'), "/app2/default/user.json ['arg']")
self.assertEqual(filter_url(
'http://d.com/app2/ctr/index.json/arg'), "/app2/ctr/index.json ['arg']")
self.assertEqual(
filter_url('http://d.com/app2/ctr/arg'), "/app2/ctr/arg")
def test_router_functions2(self):
'''
Test more functions=[something]
+6 -7
View File
@@ -843,7 +843,7 @@ class TestValidators(unittest.TestCase):
'|'.join(['Minimum length is 8',
'Maximum length is 4',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|',
'Must include at least 1 upper case',
'Must include at least 1 uppercase',
'Must include at least 1 number']))
)
rtn = IS_STRONG(es=True)('abcde')
@@ -851,7 +851,7 @@ class TestValidators(unittest.TestCase):
('abcde',
'|'.join(['Minimum length is 8',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|',
'Must include at least 1 upper case',
'Must include at least 1 uppercase',
'Must include at least 1 number']))
)
rtn = IS_STRONG(upper=0, lower=0, number=0, es=True)('Abcde1')
@@ -859,8 +859,8 @@ class TestValidators(unittest.TestCase):
('Abcde1',
'|'.join(['Minimum length is 8',
'Must include at least 1 of the following: ~!@#$%^&*()_+-=?<>,.:;{}[]|',
'May not include any upper case letters',
'May not include any lower case letters',
'May not include any uppercase letters',
'May not include any lowercase letters',
'May not include any numbers']))
)
@@ -1029,12 +1029,11 @@ this is the content of the fake file
self.assertEqual(rtn, ('2001::126c:8ffa:fe22:b3af', 'Enter valid IPv6 address'))
rtn = IS_IPV6(is_multicast=True)('ff00::126c:8ffa:fe22:b3af')
self.assertEqual(rtn, ('ff00::126c:8ffa:fe22:b3af', None))
# TODO:
# with py3.ipaddress '2001::126c:8ffa:fe22:b3af' is considered private
# with py2.ipaddress '2001::126c:8ffa:fe22:b3af' is considered private
# with gluon.contrib.ipaddr(both current and trunk) is not considered private
# rtn = IS_IPV6(is_routeable=True)('2001::126c:8ffa:fe22:b3af')
# self.assertEqual(rtn, ('2001::126c:8ffa:fe22:b3af', None))
rtn = IS_IPV6(is_routeable=False)('2001::126c:8ffa:fe22:b3af')
self.assertEqual(rtn, ('2001::126c:8ffa:fe22:b3af', None))
rtn = IS_IPV6(is_routeable=True)('ff00::126c:8ffa:fe22:b3af')
self.assertEqual(rtn, ('ff00::126c:8ffa:fe22:b3af', 'Enter valid IPv6 address'))
rtn = IS_IPV6(subnets='2001::/32')('2001::8ffa:fe22:b3af')
+37 -13
View File
@@ -2005,6 +2005,12 @@ class Auth(object):
return self.cas_validate(version=2, proxy=False)
elif args(1) == self.settings.cas_actions['proxyvalidate']:
return self.cas_validate(version=2, proxy=True)
elif (args(1) == 'p3'
and args(2) == self.settings.cas_actions['servicevalidate']):
return self.cas_validate(version=3, proxy=False)
elif (args(1) == 'p3'
and args(2) == self.settings.cas_actions['proxyvalidate']):
return self.cas_validate(version=3, proxy=True)
elif args(1) == self.settings.cas_actions['logout']:
return self.logout(next=request.vars.service or DEFAULT)
else:
@@ -2830,6 +2836,15 @@ class Auth(object):
if success:
if version == 1:
message = 'yes\n%s' % user[userfield]
elif version == 3:
username = user.get('username', user[userfield])
message = build_response(
TAG['cas:authenticationSuccess'](
TAG['cas:user'](username),
TAG['cas:attributes'](
*[TAG['cas:' + field.name](user[field.name])
for field in self.table_user()
if field.readable])))
else: # assume version 2
username = user.get('username', user[userfield])
message = build_response(
@@ -3417,7 +3432,9 @@ class Auth(object):
link = self.url(
self.settings.function, args=('verify_email', key), scheme=True)
d = dict(form.vars)
d.update(dict(key=key, link=link, username=form.vars[username]))
d.update(dict(key=key, link=link, username=form.vars[username],
firstname=form.vars['firstname'],
lastname=form.vars['lastname']))
if not (self.settings.mailer and self.settings.mailer.send(
to=form.vars.email,
subject=self.messages.verify_email_subject,
@@ -3670,7 +3687,12 @@ class Auth(object):
key = request.args[-1]
if key:
session._reset_password_key = key
redirect(self.url(args='confirm_registration'))
if next:
redirect_vars = {'_next': next}
else:
redirect_vars = {}
redirect(self.url(args='confirm_registration',
vars=redirect_vars))
else:
key = session._reset_password_key
else:
@@ -4776,6 +4798,18 @@ class Auth(object):
class Crud(object): # pragma: no cover
default_messages = dict(
submit_button = 'Submit',
delete_label = 'Check to delete',
record_created = 'Record Created',
record_updated = 'Record Updated',
record_deleted = 'Record Deleted',
update_log = 'Record %(id)s updated',
create_log = 'Record %(id)s created',
read_log = 'Record %(id)s read',
delete_log = 'Record %(id)s deleted',
)
def url(self, f=None, args=None, vars=None):
"""
This should point to the controller that exposes
@@ -4824,17 +4858,7 @@ class Crud(object): # pragma: no cover
settings.lock_keys = True
messages = self.messages = Messages(current.T)
messages.submit_button = 'Submit'
messages.delete_label = 'Check to delete'
messages.record_created = 'Record Created'
messages.record_updated = 'Record Updated'
messages.record_deleted = 'Record Deleted'
messages.update_log = 'Record %(id)s updated'
messages.create_log = 'Record %(id)s created'
messages.read_log = 'Record %(id)s read'
messages.delete_log = 'Record %(id)s deleted'
messages.update(Crud.default_messages)
messages.lock_keys = True
def __call__(self):
+14 -12
View File
@@ -17,6 +17,7 @@ import random
import inspect
import time
import os
import sys
import re
import logging
import socket
@@ -299,19 +300,20 @@ def initialize_urandom():
try:
os.urandom(1)
have_urandom = True
try:
# try to add process-specific entropy
frandom = open('/dev/urandom', 'wb')
if sys.platform != 'win32':
try:
if PY2:
frandom.write(''.join(chr(t) for t in ctokens))
else:
frandom.write(bytes([]).join(bytes([t]) for t in ctokens))
finally:
frandom.close()
except IOError:
# works anyway
pass
# try to add process-specific entropy
frandom = open('/dev/urandom', 'wb')
try:
if PY2:
frandom.write(''.join(chr(t) for t in ctokens))
else:
frandom.write(bytes([]).join(bytes([t]) for t in ctokens))
finally:
frandom.close()
except IOError:
# works anyway
pass
except NotImplementedError:
have_urandom = False
logger.warning(
+11 -16
View File
@@ -2470,7 +2470,7 @@ class IS_LIST_OF(Validator):
class IS_LOWER(Validator):
"""
Converts to lower case::
Converts to lowercase::
>>> IS_LOWER()('ABC')
('abc', None)
@@ -2485,7 +2485,7 @@ class IS_LOWER(Validator):
class IS_UPPER(Validator):
"""
Converts to upper case::
Converts to uppercase::
>>> IS_UPPER()('abc')
('ABC', None)
@@ -3025,22 +3025,22 @@ class IS_STRONG(object):
all_upper = re.findall("[A-Z]", value)
if self.upper > 0:
if not len(all_upper) >= self.upper:
failures.append(translate("Must include at least %s upper case")
failures.append(translate("Must include at least %s uppercase")
% str(self.upper))
else:
if len(all_upper) > 0:
failures.append(
translate("May not include any upper case letters"))
translate("May not include any uppercase letters"))
if isinstance(self.lower, int):
all_lower = re.findall("[a-z]", value)
if self.lower > 0:
if not len(all_lower) >= self.lower:
failures.append(translate("Must include at least %s lower case")
failures.append(translate("Must include at least %s lowercase")
% str(self.lower))
else:
if len(all_lower) > 0:
failures.append(
translate("May not include any lower case letters"))
translate("May not include any lowercase letters"))
if isinstance(self.number, int):
all_number = re.findall("[0-9]", value)
if self.number > 0:
@@ -3505,10 +3505,7 @@ class IS_IPV6(Validator):
self.error_message = error_message
def __call__(self, value):
try:
import ipaddress
except ImportError:
from gluon.contrib import ipaddr as ipaddress
from gluon._compat import ipaddress
try:
ip = ipaddress.IPv6Address(to_unicode(value))
@@ -3732,12 +3729,10 @@ class IS_IPADDRESS(Validator):
self.error_message = error_message
def __call__(self, value):
try:
from ipaddress import ip_address as IPAddress
from ipaddress import IPv6Address, IPv4Address
except ImportError:
from gluon.contrib.ipaddr import (IPAddress, IPv4Address,
IPv6Address)
from gluon._compat import ipaddress
IPAddress = ipaddress.ip_address
IPv6Address = ipaddress.IPv6Address
IPv4Address = ipaddress.IPv4Address
try:
ip = IPAddress(to_unicode(value))
+13 -7
View File
@@ -18,7 +18,7 @@ legacy_db(legacy_db.mytable.id>0).select()
If the script crashes this is might be due to that fact that the data_type_map dictionary below is incomplete.
Please complete it, improve it and continue.
Created by Falko Krause, minor modifications by Massimo Di Pierro and Ron McOuat
Created by Falko Krause, minor modifications by Massimo Di Pierro, Ron McOuat and Marvi Benedet
'''
import subprocess
import re
@@ -52,10 +52,11 @@ data_type_map = dict(
)
def mysql(database_name, username, password):
def mysql(database_name, username, password, host):
p = subprocess.Popen(['mysql',
'--user=%s' % username,
'--password=%s' % password,
'--host=%s' % host,
'--execute=show tables;',
database_name],
stdin=subprocess.PIPE,
@@ -64,14 +65,15 @@ def mysql(database_name, username, password):
sql_showtables, stderr = p.communicate()
tables = [re.sub(
'\|\s+([^\|*])\s+.*', '\1', x) for x in sql_showtables.split()[1:]]
connection_string = "legacy_db = DAL('mysql://%s:%s@localhost/%s')" % (
username, password, database_name)
connection_string = "legacy_db = DAL('mysql://%s:%s@%s/%s')" % (
username, password, host, database_name)
legacy_db_table_web2py_code = []
for table_name in tables:
#get the sql create statement
p = subprocess.Popen(['mysqldump',
'--user=%s' % username,
'--password=%s' % password,
'--host=%s' % host,
'--skip-add-drop-table',
'--no-data', database_name,
table_name], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -106,9 +108,13 @@ def mysql(database_name, username, password):
legacy_db_table_web2py_code)
return legacy_db_web2py_code
regex = re.compile('(.*?):(.*?)@(.*)')
regex = re.compile('(.*):(.*)@((.*)/)?(.*)')
if len(sys.argv) < 2 or not regex.match(sys.argv[1]):
print 'USAGE:\n\n extract_mysql_models.py username:password@data_basename\n\n'
print 'USAGE:\n\n extract_mysql_models.py username:password@[host/]data_basename\n\n'
else:
m = regex.match(sys.argv[1])
print mysql(m.group(3), m.group(1), m.group(2))
username = m.group(1)
password = m.group(2)
host = m.group(4) or 'localhost'
db_name = m.group(5)
print mysql(database_name = db_name, username = username, password = password, host = host)
@@ -216,6 +216,7 @@ fi
/etc/init.d/nginx start
systemctl start emperor.uwsgi.service
systemctl enable emperor.uwsgi.service
echo <<EOF
you can stop uwsgi and nginx with