diff --git a/flask_ask/convert.py b/flask_ask/convert.py index fcc6a8a..44cbeca 100644 --- a/flask_ask/convert.py +++ b/flask_ask/convert.py @@ -8,15 +8,15 @@ _DATE_PATTERNS = { # "today", "tomorrow", "november twenty-fifth": 2015-11-25 - '^\d{4}-\d{2}-\d{2}$': '%Y-%m-%d', + r'^\d{4}-\d{2}-\d{2}$': '%Y-%m-%d', # "this week", "next week": 2015-W48 - '^\d{4}-W\d{2}$': '%Y-W%U-%w', + r'^\d{4}-W\d{2}$': '%Y-W%U-%w', # "this weekend": 2015-W48-WE - '^\d{4}-W\d{2}-WE$': '%Y-W%U-WE-%w', + r'^\d{4}-W\d{2}-WE$': '%Y-W%U-WE-%w', # "this month": 2015-11 - '^\d{4}-\d{2}$': '%Y-%m', + r'^\d{4}-\d{2}$': '%Y-%m', # "next year": 2016 - '^\d{4}$': '%Y', + r'^\d{4}$': '%Y', } diff --git a/flask_ask/core.py b/flask_ask/core.py index 6ebffdb..125ca2c 100644 --- a/flask_ask/core.py +++ b/flask_ask/core.py @@ -3,14 +3,14 @@ import yaml import inspect import io -from datetime import datetime +from datetime import datetime, timezone from functools import wraps, partial import aniso8601 -from werkzeug.contrib.cache import SimpleCache +from cachelib import SimpleCache from werkzeug.local import LocalProxy, LocalStack from jinja2 import BaseLoader, ChoiceLoader, TemplateNotFound -from flask import current_app, json, request as flask_request, _app_ctx_stack +from flask import current_app, json, request as flask_request, g from . import verifier, logger from .convert import to_date, to_time, to_timedelta @@ -524,47 +524,46 @@ def wrapper(*args, **kwargs): @property def request(self): - return getattr(_app_ctx_stack.top, '_ask_request', None) + return g.get('_ask_request') @request.setter def request(self, value): - _app_ctx_stack.top._ask_request = value + g._ask_request = value @property def session(self): - return getattr(_app_ctx_stack.top, '_ask_session', models._Field()) + return g.get('_ask_session', models._Field()) @session.setter def session(self, value): - _app_ctx_stack.top._ask_session = value + g._ask_session = value @property def version(self): - return getattr(_app_ctx_stack.top, '_ask_version', None) + return g.get('_ask_version') @version.setter def version(self, value): - _app_ctx_stack.top._ask_version = value + g._ask_version = value @property def context(self): - return getattr(_app_ctx_stack.top, '_ask_context', None) + return g.get('_ask_context') @context.setter def context(self, value): - _app_ctx_stack.top._ask_context = value + g._ask_context = value @property def convert_errors(self): - return getattr(_app_ctx_stack.top, '_ask_convert_errors', None) + return g.get('_ask_convert_errors') @convert_errors.setter def convert_errors(self, value): - _app_ctx_stack.top._ask_convert_errors = value + g._ask_convert_errors = value @property def current_stream(self): - #return getattr(_app_ctx_stack.top, '_ask_current_stream', models._Field()) user = self._get_user() if user: stream = top_stream(self.stream_cache, user) @@ -732,10 +731,10 @@ def _parse_timestamp(timestamp): # raised by aniso8601 if raw_timestamp is not valid string # in ISO8601 format try: - return datetime.utcfromtimestamp(timestamp) + return datetime.fromtimestamp(timestamp, timezone.utc).replace(tzinfo=None) except: # relax the timestamp a bit in case it was sent in millis - return datetime.utcfromtimestamp(timestamp/1000) + return datetime.fromtimestamp(timestamp/1000, timezone.utc).replace(tzinfo=None) raise ValueError('Invalid timestamp value! Cannot parse from either ISO8601 string or UTC timestamp.') diff --git a/requirements-dev.txt b/requirements-dev.txt index f8d2793..3c6e611 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,5 +1,6 @@ -r requirements.txt -mock==2.0.0 -requests==2.13.0 -tox==2.7.0 +mock==5.1.0 +requests==2.32.3 +tox==4.23.2 +urllib3==2.2.3 diff --git a/requirements.txt b/requirements.txt index f6e850d..932d4ec 100644 --- a/requirements.txt +++ b/requirements.txt @@ -1,7 +1,9 @@ -aniso8601==1.2.0 -Flask==1.1.1 -cryptography==2.1.4 -pyOpenSSL==17.0.0 -PyYAML==5.4 -six==1.11.0 -Werkzeug==0.16.1 +aniso8601==1.3.0 +Flask==3.1.0 +cryptography==43.0.3 +pyOpenSSL==24.2.1 +PyYAML==6.0.2 +six==1.16.0 +Werkzeug==3.1.3 +markupsafe==3.0.2 +cachelib==0.13.0 diff --git a/tests/test_audio.py b/tests/test_audio.py index 310d082..d33fd3e 100644 --- a/tests/test_audio.py +++ b/tests/test_audio.py @@ -1,17 +1,20 @@ import unittest -from mock import patch, MagicMock +from unittest.mock import patch +from mock import MagicMock from flask import Flask from flask_ask import Ask, audio from flask_ask.models import _Field +app = Flask(__name__) class AudioUnitTests(unittest.TestCase): def setUp(self): - self.ask_patcher = patch('flask_ask.core.find_ask', return_value=Ask()) - self.ask_patcher.start() - self.context_patcher = patch('flask_ask.models.context', return_value=MagicMock()) - self.context_patcher.start() + with app.app_context(): + self.ask_patcher = patch('flask_ask.core.find_ask', return_value=Ask()) + self.ask_patcher.start() + self.context_patcher = patch('flask_ask.models.context', return_value=MagicMock()) + self.context_patcher.start() def tearDown(self): self.ask_patcher.stop() diff --git a/tests/test_cache.py b/tests/test_cache.py index 418dde8..3eafe3f 100644 --- a/tests/test_cache.py +++ b/tests/test_cache.py @@ -1,6 +1,6 @@ import unittest from mock import patch, Mock -from werkzeug.contrib.cache import SimpleCache +from cachelib import SimpleCache from flask_ask.core import Ask from flask_ask.cache import push_stream, pop_stream, top_stream, set_stream diff --git a/tests/test_core.py b/tests/test_core.py index 6b424c4..ef055c3 100644 --- a/tests/test_core.py +++ b/tests/test_core.py @@ -3,7 +3,7 @@ from aniso8601.timezone import UTCOffset, build_utcoffset from flask_ask.core import Ask -from datetime import datetime, timedelta +from datetime import datetime, timedelta, timezone from mock import patch, MagicMock import json @@ -58,7 +58,7 @@ def test_tries_parsing_on_valueerror(self): # should cause a ValueError normally with self.assertRaises(ValueError): - datetime.utcfromtimestamp(max_timestamp) + datetime.fromtimestamp(max_timestamp, timezone.utc).replace(tzinfo=None) # should safely parse, assuming scale change needed # note: this assert looks odd, but Py2 handles the parsing