Skip to content

Commit

Permalink
Merge branch 'master' into typos2
Browse files Browse the repository at this point in the history
  • Loading branch information
mdipierro committed Apr 19, 2018
2 parents 77ebad5 + 5df2317 commit 039da93
Show file tree
Hide file tree
Showing 11 changed files with 60 additions and 197 deletions.
2 changes: 1 addition & 1 deletion applications/examples/views/default/download.html
Expand Up @@ -81,7 +81,7 @@ <h3>Caveats</h3>

<h3 id="license">License</h3>
<p>Web2py code is released under <a href="http://www.gnu.org/licenses/lgpl.html">LGPLv3 License</a>. This license does not extend to third party libraries distributed with web2py (which can be MIT, BSD or Apache type licenses) nor does it extend to applications built with web2py (under the terms of the LGPL.</p>
<p>Applications built with web2py can be released under any license the author wishes as long they do not contain web2py code. They can link unmodified web2py libraries and they can be distributed with official web2py binaries. In particular web2py applications can be distributed in closed source. The admin interface provides a button to byte-code compile.</p>
<p>Applications built with web2py can be released under any license the author wishes as long as they do not contain web2py code. They can link unmodified web2py libraries and they can be distributed with official web2py binaries. In particular web2py applications can be distributed in closed source. The admin interface provides a button to byte-code compile.</p>
<p>It is fine to distribute web2py (source or compiled) with your applications as long as you make it clear in the license where your application ends and web2py starts.</p>
<p>web2py is copyrighted by Massimo Di Pierro. The web2py trademark is owned by Massimo Di Pierro.</p>
<a class="btn btn-small rounded" href="{{=URL('license')}}">read more</a>
Expand Down
10 changes: 5 additions & 5 deletions applications/examples/views/default/examples.html
Expand Up @@ -50,10 +50,10 @@ <h3>Example {{=c}}{{c+=1}}</h3><b>In controller: simple_examples.py</b>

<b>and view: simple_examples/hello3.html</b>
{{=CODE(open(os.path.join(request.folder,'views/simple_examples/hello3.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
<p>If you return a dictionary, the variables defined in the dictionery are visible to the view (template).
<p>If you return a dictionary, the variables defined in the dictionary are visible to the view (template).
<br/>Try it here: <a class="btn" href="/{{=request.application}}/simple_examples/hello3.html">hello3</a></p>

<p>Actions can also be be rendered in other formsts like JSON, <a href="/{{=request.application}}/simple_examples/hello3.json">hello3.json</a>, and XML, <a href="/{{=request.application}}/simple_examples/hello3.xml">hello3.xml</a></p>
<p>Actions can also be be rendered in other forms like JSON, <a href="/{{=request.application}}/simple_examples/hello3.json">hello3.json</a>, and XML, <a href="/{{=request.application}}/simple_examples/hello3.xml">hello3.xml</a></p>

<h3>Example {{=c}}{{c+=1}}</h3><b>In controller: simple_examples.py</b>
{{=CODE("""
Expand All @@ -69,7 +69,7 @@ <h3>Example {{=c}}{{c+=1}}</h3><b>In controller: simple_examples.py</b>
def hello5():
return HTML(BODY(H1(T('Hello World'),_style="color: red;"))).xml() # .xml to serialize
""".strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}
<p>You can also generate HTML using helper objects HTML, BODY, H1, etc. Each of these tags is a class and the views know how to render the corresponding objects. The method .xml() serializes them and produce html/xml code for the page.
<p>You can also generate HTML using helper objects HTML, BODY, H1, etc. Each of these tags is a class and the views know how to render the corresponding objects. The method .xml() serializes them and produces html/xml code for the page.
Each tag, DIV for example, takes three types of arguments:</p>
<ul>
<li>unnamed arguments, they correspond to nested tags</li>
Expand Down Expand Up @@ -201,11 +201,11 @@ <h2 id="session_examples">Session Examples</h2>
<h3>Example {{=c}}{{c+=1}}</h3><b>In controller: session_examples.py </b>
{{=CODE("""
def counter():
session.counter = (sesstion.counter or 0) + 1
session.counter = (session.counter or 0) + 1
return dict(counter=session.counter)
""".strip(),language='web2py',link=URL('global','vars'),_class='boxCode')}}<b>and view: session_examples/counter.html</b>
{{=CODE(open(os.path.join(request.folder,'views/session_examples/counter.html'),'r').read(),language='html',link=URL('global','vars'),_class='boxCode')}}
<p>Click to count. The session.counter is persistent for this user and application. Every applicaiton within the system has its own separate session management.
<p>Click to count. The session.counter is persistent for this user and application. Every application within the system has its own separate session management.
<br/>Try it here: <a class="btn" href="/{{=request.application}}/session_examples/counter">counter</a></p>

<h2 id="template_examples">Template Examples</h2>
Expand Down
1 change: 1 addition & 0 deletions applications/examples/views/default/who.html
Expand Up @@ -150,6 +150,7 @@ <h3>
<li><a href="http://www.python.org">Python</a> created by Guido van Rossum.</li>
<li>Rocket Web Server developed by Timothy Farrell.</li>
<li><a href="http://codemirror.net/">CodeMirror</a></li>

<li><a href="http://pyrtf.sourceforge.net/">PyRTF</a> developed by Simon Cusack and revised by Grant Edwards</li>
<li><a href="http://www.dalkescientific.com/Python/PyRSS2Gen.html">PyRSS2Gen</a> developed by Dalke Scientific Software</li>
<li><a href="http://www.feedparser.org/">feedparser</a> developed by Mark Pilgrim</li>
Expand Down
20 changes: 15 additions & 5 deletions gluon/contrib/login_methods/ldap_auth.py
Expand Up @@ -170,7 +170,9 @@ def ldap_auth(server='ldap',
is "error" and can be set to error, warning, info, debug.
"""
logger = logging.getLogger('web2py.auth.ldap_auth')
if logging_level == 'error':
if isinstance(logging_level, int):
logger.setLevel(logging_level)
elif logging_level == 'error':
logger.setLevel(logging.ERROR)
elif logging_level == 'warning':
logger.setLevel(logging.WARNING)
Expand Down Expand Up @@ -398,17 +400,25 @@ def ldap_auth_aux(username,
if manage_user:
logger.info('[%s] Manage user data' % str(username))
try:
user_firstname = result[user_firstname_attrib][0]
if user_firstname_part is not None:
store_user_firstname = result[user_firstname_attrib][0].split(' ', 1)[user_firstname_part]
store_user_firstname = user_firstname.split(
b' ' if isinstance(user_firstname, bytes) else ' ',
1
)[user_firstname_part]
else:
store_user_firstname = result[user_firstname_attrib][0]
store_user_firstname = user_firstname
except KeyError as e:
store_user_firstname = None
try:
user_lastname = result[user_lastname_attrib][0]
if user_lastname_part is not None:
store_user_lastname = result[user_lastname_attrib][0].split(' ', 1)[user_lastname_part]
store_user_lastname = user_lastname.split(
b' ' if isinstance(user_lastname, bytes) else ' ',
1
)[user_lastname_part]
else:
store_user_lastname = result[user_lastname_attrib][0]
store_user_lastname = user_lastname
except KeyError as e:
store_user_lastname = None
try:
Expand Down
4 changes: 2 additions & 2 deletions gluon/contrib/redis_cache.py
Expand Up @@ -10,7 +10,7 @@
import time
import re
import logging
import thread
from threading import Lock
import random
from gluon import current
from gluon.cache import CacheAbstract
Expand All @@ -19,7 +19,7 @@

logger = logging.getLogger("web2py.cache.redis")

locker = thread.allocate_lock()
locker = Lock()


def RedisCache(redis_conn=None, debug=False, with_lock=False, fail_gracefully=False, db=None):
Expand Down
11 changes: 6 additions & 5 deletions gluon/contrib/redis_session.py
Expand Up @@ -8,15 +8,16 @@
"""

import logging
import thread
from threading import Lock
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

logger = logging.getLogger("web2py.session.redis")

locker = thread.allocate_lock()
locker = Lock()


def RedisSession(redis_conn, session_expiry=False, with_lock=False, db=None):
Expand All @@ -43,7 +44,7 @@ def RedisSession(redis_conn, session_expiry=False, with_lock=False, db=None):
try:
instance_name = 'redis_instance_' + current.request.application
if not hasattr(RedisSession, instance_name):
setattr(RedisSession, instance_name,
setattr(RedisSession, instance_name,
RedisClient(redis_conn, session_expiry=session_expiry, with_lock=with_lock))
return getattr(RedisSession, instance_name)
finally:
Expand Down Expand Up @@ -185,8 +186,8 @@ def select(self):
if rtn:
if self.unique_key:
# make sure the id and unique_key are correct
if rtn['unique_key'] == self.unique_key:
rtn['update_record'] = self.update # update record support
if rtn[b'unique_key'] == to_bytes(self.unique_key):
rtn[b'update_record'] = self.update # update record support
else:
rtn = None
return [Storage(rtn)] if rtn else []
Expand Down
4 changes: 2 additions & 2 deletions gluon/contrib/redis_utils.py
Expand Up @@ -11,7 +11,7 @@
"""

import logging
import thread
from threading import Lock
import time
from gluon import current

Expand All @@ -26,7 +26,7 @@
raise RuntimeError('Needs redis library to work')


locker = thread.allocate_lock()
locker = Lock()


def RConn(*args, **vars):
Expand Down
22 changes: 11 additions & 11 deletions gluon/globals.py
Expand Up @@ -14,7 +14,7 @@
"""
from gluon._compat import pickle, StringIO, copyreg, Cookie, urlparse, PY2, iteritems, to_unicode, to_native, \
unicodeT, long, hashlib_md5, urllib_quote
to_bytes, unicodeT, long, hashlib_md5, urllib_quote
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
Expand Down Expand Up @@ -225,7 +225,7 @@ def parse_post_vars(self):
# instead of load.
# This line can be simplified to json_vars = json_parser.load(body)
# if and when we drop support for python versions under 3.6
json_vars = json_parser.loads(to_native(body.read()))
json_vars = json_parser.loads(to_native(body.read()))
except:
# incoherent request bodies can still be parsed "ad-hoc"
json_vars = {}
Expand Down Expand Up @@ -344,8 +344,8 @@ def user_agent(self):
user_agent = Storage(user_agent)
user_agent.is_mobile = 'Mobile' in http_user_agent
user_agent.is_tablet = 'Tablet' in http_user_agent
session._user_agent = user_agent
session._user_agent = user_agent

return user_agent

def requires_https(self):
Expand Down Expand Up @@ -485,12 +485,12 @@ def include_files(self, extensions=None):
#
# We will only minify and concat adjacent internal files as there's
# no way to know if changing the order with which the files are apppended
# will break things since the order matters in both CSS and JS and
# will break things since the order matters in both CSS and JS and
# internal files may be interleaved with external ones.
files = []
# For the adjacent list we're going to use storage List to both distinguish
# from the regular list and so we can add attributes
internal = List()
internal = List()
internal.has_js = False
internal.has_css = False
done = set() # to remove duplicates
Expand All @@ -513,7 +513,7 @@ def include_files(self, extensions=None):
if item.endswith('.js'):
internal.has_js = True
if item.endswith('.css'):
internal.has_css = True
internal.has_css = True
if internal:
files.append(internal)

Expand All @@ -537,7 +537,7 @@ def call_minify(files=f):
time_expire)
else:
files[i] = call_minify()

def static_map(s, item):
if isinstance(item, str):
f = item.lower().split('?')[0]
Expand Down Expand Up @@ -967,7 +967,7 @@ def connect(self,
if row:
# rows[0].update_record(locked=True)
# Unpickle the data
session_data = pickle.loads(row.session_data)
session_data = pickle.loads(row[b'session_data'])
self.update(session_data)
response.session_new = False
else:
Expand Down Expand Up @@ -1049,7 +1049,7 @@ def renew(self, clear_session=False):
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 row[b'unique_key'] == to_bytes(unique_key):
table._db(table.id == record_id).update(unique_key=new_unique_key)
else:
record_id = None
Expand Down Expand Up @@ -1167,7 +1167,7 @@ def _try_store_in_cookie(self, request, response):
compression_level=compression_level)
rcookies = response.cookies
rcookies.pop(name, None)
rcookies[name] = value
rcookies[name] = to_native(value)
rcookies[name]['path'] = '/'
expires = response.session_cookie_expires
if isinstance(expires, datetime.datetime):
Expand Down
37 changes: 15 additions & 22 deletions gluon/tests/test_tools.py
Expand Up @@ -17,7 +17,7 @@
from gluon.dal import DAL, Field
from pydal.objects import Table
from gluon import tools
from gluon.tools import Auth, Mail, Recaptcha, Recaptcha2, prettydate, Expose
from gluon.tools import Auth, Mail, Recaptcha2, prettydate, Expose
from gluon._compat import PY2
from gluon.globals import Request, Response, Session
from gluon.storage import Storage
Expand Down Expand Up @@ -208,14 +208,6 @@ def test_attachment(self):
self.assertTrue('Content-Id: <trololo>' in message.payload)


# class TestRecaptcha(unittest.TestCase):
# def test_Recaptcha(self):
# from html import FORM
# form = FORM(Recaptcha(public_key='public_key', private_key='private_key'))
# self.assertEqual(form.xml(),
# '<form action="#" enctype="multipart/form-data" method="post"><div id="recaptcha"><script><!--\nvar RecaptchaOptions = {};\n//--></script><script src="http://www.google.com/recaptcha/api/challenge?k=public_key" type="text/javascript"></script><noscript><iframe frameborder="0" height="300" src="http://www.google.com/recaptcha/api/noscript?k=public_key" width="500"></iframe><br /><input name="recaptcha_response_field" type="hidden" value="manual_challenge" /></noscript></div></form>')
#
#
# class TestRecaptcha2(unittest.TestCase):
# def test_Recaptcha2(self):
# from html import FORM
Expand Down Expand Up @@ -248,7 +240,6 @@ def setUp(self):
self.user_data['password'])[0]))
self.jwtauth = AuthJWT(self.auth, secret_key='secret', verify_expiration=True)


def test_jwt_token_manager(self):
import gluon.serializers
self.request.vars.update(self.user_data)
Expand All @@ -260,7 +251,6 @@ def test_jwt_token_manager(self):
self.token = self.jwtauth.jwt_token_manager()
self.assertIsNotNone(self.token)


def test_allows_jwt(self):
import gluon.serializers
self.request.vars.update(self.user_data)
Expand All @@ -270,11 +260,13 @@ def test_allows_jwt(self):
del self.request.vars['password']
self.token = self.jwtauth.jwt_token_manager()
self.request.vars._token = gluon.serializers.json_parser.loads(self.token)['token']

@self.jwtauth.allows_jwt()
def optional_auth():
self.assertEqual(self.user_data['username'], self.auth.user.username)
optional_auth()


@unittest.skipIf(IS_IMAP, "TODO: Imap raises 'Connection refused'")
# class TestAuth(unittest.TestCase):
#
Expand Down Expand Up @@ -495,8 +487,6 @@ def optional_auth():
# # impersonate_form = auth.impersonate(user_id=omer_id)
# # self.assertTrue(auth.is_impersonating())
# # self.assertEqual(impersonate_form, 'test')


class TestAuth(unittest.TestCase):

def myassertRaisesRegex(self, *args, **kwargs):
Expand Down Expand Up @@ -904,7 +894,7 @@ def test_has_membership(self):
self.assertEqual(count_log_event_test_after, count_log_event_test_before)

def test_add_membership(self):
user = self.db(self.db.auth_user.username == 'bart').select().first() # bypass login_bare()
user = self.db(self.db.auth_user.username == 'bart').select().first() # bypass login_bare()
user_id = user.id
role_name = 'test_add_membership_group'
group_id = self.auth.add_group(role_name)
Expand Down Expand Up @@ -1174,34 +1164,37 @@ def test_prettydate(self):

pjoin = os.path.join


def have_symlinks():
return os.name == 'posix'


class Test_Expose__in_base(unittest.TestCase):

def test_in_base(self):
are_under = [ # (sub, base)
are_under = [
# (sub, base)
('/foo/bar', '/foo'),
('/foo', '/foo'),
('/foo', '/'),
('/', '/'),
]
for sub, base in are_under:
self.assertTrue( Expose._Expose__in_base(subdir=sub, basedir=base, sep='/'),
'%s is not under %s' % (sub, base) )
self.assertTrue(Expose._Expose__in_base(subdir=sub, basedir=base, sep='/'),
'%s is not under %s' % (sub, base))

def test_not_in_base(self):
are_not_under = [ # (sub, base)
are_not_under = [
# (sub, base)
('/foobar', '/foo'),
('/foo', '/foo/bar'),
('/bar', '/foo'),
('/foo/bar', '/bar'),
('/', '/x'),
]
for sub, base in are_not_under:
self.assertFalse( Expose._Expose__in_base(subdir=sub, basedir=base, sep='/'),
'%s should not be under %s' % (sub, base) )
self.assertFalse(Expose._Expose__in_base(subdir=sub, basedir=base, sep='/'),
'%s should not be under %s' % (sub, base))


class TestExpose(unittest.TestCase):
Expand Down Expand Up @@ -1237,7 +1230,7 @@ def tearDown(self):
shutil.rmtree(self.base_dir)

def make_dirs(self):
"""setup direcotry strucutre"""
"""setup directory structure"""
for d in (['inside'],
['inside', 'dir1'],
['inside', 'dir2'],
Expand All @@ -1257,7 +1250,7 @@ def make_readme(self):
f.write('README content')

def make_symlinks(self):
"""setup extenstion for posix systems"""
"""setup extension for posix systems"""
# inside links
os.symlink(
pjoin(self.base_dir, 'inside', 'dir1'),
Expand Down

0 comments on commit 039da93

Please sign in to comment.