From a79ad250019691ba8a81fdf07b14922587cf1cc2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Boris=20Aramis=20Aguilar=20Rodr=C3=ADguez?= Date: Thu, 1 Nov 2018 15:04:22 -0600 Subject: [PATCH 1/4] redis_scheduler failing redis_scheduler failed when calculating next_run_time (method total_seconds() belongs to timedelta) --- gluon/contrib/redis_scheduler.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gluon/contrib/redis_scheduler.py b/gluon/contrib/redis_scheduler.py index 6a3f00fc..bc39201d 100644 --- a/gluon/contrib/redis_scheduler.py +++ b/gluon/contrib/redis_scheduler.py @@ -487,7 +487,7 @@ class RScheduler(Scheduler): # calc next_run_time based on available slots # see #1191 next_run_time = task.start_time - secondspassed = self.total_seconds(now - next_run_time) + secondspassed = (now - next_run_time).total_seconds() steps = secondspassed // task.period + 1 next_run_time += datetime.timedelta(seconds=task.period * steps) From 7318d28f1aa8d24a4b2b910910e0b721c547e62c Mon Sep 17 00:00:00 2001 From: Vinyl Darkscratch Date: Sat, 3 Nov 2018 21:06:43 -0800 Subject: [PATCH 2/4] Add aspect ratio to IS_IMAGE() validator --- gluon/validators.py | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/gluon/validators.py b/gluon/validators.py index 7e47f79c..541dddd1 100644 --- a/gluon/validators.py +++ b/gluon/validators.py @@ -3230,8 +3230,10 @@ class IS_IMAGE(Validator): ('jpg' extension of uploaded file counts as 'jpeg') maxsize: iterable containing maximum width and height of the image minsize: iterable containing minimum width and height of the image + aspectratio: iterable containing target aspect ratio Use (-1, -1) as minsize to pass image size check. + Use (-1, -1) as aspectratio to pass aspect ratio check. Examples: Check if uploaded file is in any of supported image formats: @@ -3247,17 +3249,24 @@ class IS_IMAGE(Validator): INPUT(_type='file', _name='name', requires=IS_IMAGE(extensions=('png'), maxsize=(200, 200))) + + Check if uploaded file has a 16:9 aspect ratio: + + INPUT(_type='file', _name='name', + requires=IS_IMAGE(aspectratio=(16, 9))) """ def __init__(self, extensions=('bmp', 'gif', 'jpeg', 'png'), maxsize=(10000, 10000), minsize=(0, 0), + aspectratio=(-1, -1), error_message='Invalid image'): self.extensions = extensions self.maxsize = maxsize self.minsize = minsize + self.aspectratio = aspectratio self.error_message = error_message def __call__(self, value): @@ -3279,8 +3288,16 @@ class IS_IMAGE(Validator): else: width = -1 height = -1 + assert self.minsize[0] <= width <= self.maxsize[0] \ and self.minsize[1] <= height <= self.maxsize[1] + + if self.aspectratio > (-1, -1): + target_ratio = (1.0 * self.aspectratio[1]) / self.aspectratio[0] + actual_ratio = (1.0 * height) / width + + assert actual_ratio == target_ratio + value.file.seek(0) return (value, None) except Exception as e: From 62df950f5071680475f622ae64006a9b11a67a21 Mon Sep 17 00:00:00 2001 From: Vinyl Darkscratch Date: Sat, 3 Nov 2018 21:17:13 -0800 Subject: [PATCH 3/4] Add aspect ratio validation tests --- gluon/tests/test_validators.py | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/gluon/tests/test_validators.py b/gluon/tests/test_validators.py index 73712664..8afccc5a 100644 --- a/gluon/tests/test_validators.py +++ b/gluon/tests/test_validators.py @@ -977,6 +977,8 @@ class TestValidators(unittest.TestCase): self.assertEqual(rtn, (img, 'oops')) rtn = IS_IMAGE(error_message='oops', minsize=(100, 50))(img) self.assertEqual(rtn, (img, 'oops')) + rtn = IS_IMAGE(error_message='oops', aspectratio=(1, 1))(img) + self.assertEqual(rtn, (img, 'oops')) img = DummyImageFile('test', 'gif', 50, 100) rtn = IS_IMAGE()(img) @@ -985,6 +987,8 @@ class TestValidators(unittest.TestCase): self.assertEqual(rtn, (img, 'oops')) rtn = IS_IMAGE(error_message='oops', minsize=(100, 50))(img) self.assertEqual(rtn, (img, 'oops')) + rtn = IS_IMAGE(error_message='oops', aspectratio=(1, 1))(img) + self.assertEqual(rtn, (img, 'oops')) img = DummyImageFile('test', 'jpeg', 50, 100) rtn = IS_IMAGE()(img) @@ -993,6 +997,8 @@ class TestValidators(unittest.TestCase): self.assertEqual(rtn, (img, 'oops')) rtn = IS_IMAGE(error_message='oops', minsize=(100, 50))(img) self.assertEqual(rtn, (img, 'oops')) + rtn = IS_IMAGE(error_message='oops', aspectratio=(1, 1))(img) + self.assertEqual(rtn, (img, 'oops')) img = DummyImageFile('test', 'png', 50, 100) rtn = IS_IMAGE()(img) @@ -1001,6 +1007,8 @@ class TestValidators(unittest.TestCase): self.assertEqual(rtn, (img, 'oops')) rtn = IS_IMAGE(error_message='oops', minsize=(100, 50))(img) self.assertEqual(rtn, (img, 'oops')) + rtn = IS_IMAGE(error_message='oops', aspectratio=(1, 1))(img) + self.assertEqual(rtn, (img, 'oops')) img = DummyImageFile('test', 'xls', 50, 100) rtn = IS_IMAGE(error_message='oops')(img) From 66f65498177dfa03f2a042b13c0e86dddb20b326 Mon Sep 17 00:00:00 2001 From: erbalito <45042116+erbalito@users.noreply.github.com> Date: Wed, 14 Nov 2018 12:47:04 -0300 Subject: [PATCH 4/4] Update redis_cache.py to allow sharing cache between different applications I'm not sure if this would help someone else. I've always had this scenario where some of my web2py applications share the models, and therefore, need to share the cache (I use Redis). In the past I've asked if there was any possibility to share cache between applications, but I got no answers: https://groups.google.com/forum/#!searchin/web2py/share$20cache$20application%7Csort:date/web2py/iNCzMq8ADnw/ufyPBWajBQAJ Anyway, I've noticed that I could make a simple change to redis_cache.py to achieve what I was looking for: I've added the optional argument "application" to RedisCache(). If you inspect the RedisCache() code, you will notice that previously it was forced to use current.request.application for the instance_name. With this simple change I did, it's possible to provide an application name to the RedisCache() constructor. This has worked like a charm for my specific scenario, and I think I can say that it has backwards compatibility. Still, if this proposal isn't accepted, I would like to hear about some alternative to share cache between applications. Thanks! --- gluon/contrib/redis_cache.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/gluon/contrib/redis_cache.py b/gluon/contrib/redis_cache.py index ddfd3a67..c44a5b7c 100644 --- a/gluon/contrib/redis_cache.py +++ b/gluon/contrib/redis_cache.py @@ -22,7 +22,7 @@ logger = logging.getLogger("web2py.cache.redis") locker = Lock() -def RedisCache(redis_conn=None, debug=False, with_lock=False, fail_gracefully=False, db=None): +def RedisCache(redis_conn=None, debug=False, with_lock=False, fail_gracefully=False, db=None, application=None): """ Usage example: put in models:: @@ -83,7 +83,7 @@ def RedisCache(redis_conn=None, debug=False, with_lock=False, fail_gracefully=Fa locker.acquire() try: - instance_name = 'redis_instance_' + current.request.application + instance_name = 'redis_instance_' + (application or current.request.application) if not hasattr(RedisCache, instance_name): setattr(RedisCache, instance_name, RedisClient(redis_conn=redis_conn, debug=debug,