Compare commits
64 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| f31c9002f7 | |||
| 6354fbedf8 | |||
| cc11a14ce3 | |||
| 2fa9597cd8 | |||
| c9d656ea45 | |||
| 1eec01b830 | |||
| c10983b191 | |||
| 975ab7b923 | |||
| 16f60d5cff | |||
| 930370ee91 | |||
| 215abc9e4f | |||
| b6e5e16526 | |||
| b2548f5631 | |||
| f14c384d83 | |||
| 9f186e5d5d | |||
| 51dd427b9e | |||
| 7b3fe560ed | |||
| bd526452a8 | |||
| d862da3543 | |||
| 0165cfadef | |||
| 46b7716b1d | |||
| 7e5277030a | |||
| b2e03c9dee | |||
| 0644df5283 | |||
| 4acd9f8f2b | |||
| ce0c5f2d5a | |||
| 28b0385d9b | |||
| ac9bccb9a2 | |||
| aa5b40528f | |||
| 96efc7bfce | |||
| aa584faed6 | |||
| e7cab3b975 | |||
| 867f93b634 | |||
| efff27ffe4 | |||
| 637579f531 | |||
| 52fe4407b8 | |||
| fc0add67b5 | |||
| 3d2834c81a | |||
| 0b8ecea4dc | |||
| 67945c2d5c | |||
| c600854f4b | |||
| 2c70a858f1 | |||
| ad9ebea900 | |||
| c72330f2cd | |||
| 091d9c74b0 | |||
| bebdbd9d5e | |||
| 05e28ddffd | |||
| e19435dbcf | |||
| 90ee6f3754 | |||
| d51ea90e18 | |||
| 3fed558bdd | |||
| 870d9d3e57 | |||
| 0a07af55f9 | |||
| f7adfbde76 | |||
| 75c1d80824 | |||
| c64a9192d4 | |||
| 8e79e49ae3 | |||
| 46ce04355f | |||
| 6b1225da02 | |||
| 4ea31820aa | |||
| 8e1630843a | |||
| 2d4817841f | |||
| 4226b6d0e1 | |||
| 3e2b8f89aa |
@@ -13,6 +13,7 @@
|
||||
*.orig
|
||||
Thumbs.db
|
||||
.DS_Store
|
||||
*.DS_Store
|
||||
index.yaml
|
||||
routes.py
|
||||
logging.conf
|
||||
|
||||
+1
-1
@@ -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']
|
||||
|
||||
@@ -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/" +
|
||||
|
||||
@@ -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',
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
+760
-202
File diff suppressed because it is too large
Load Diff
@@ -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']
|
||||
|
||||
@@ -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']
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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
@@ -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():
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
Submodule gluon/packages/dal updated: 12bc6d9740...4d22bb4f84
+1
-1
@@ -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
@@ -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:
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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))
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user