diff --git a/CHANGELOG.md b/CHANGELOG.md index 5575a9c57..04bc9605e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,7 +4,35 @@ Categories: Added, Removed, Changed, Fixed, Nonfunctional, Deprecated ## Unreleased -- Fix recursion in sceptre_user_data becoming infinite +## 2.2.1 (2019.08.19) + +### Fixed + +- `typing` install dependency for Python version < 3.5 +- Race condition in stacks causing RecurrsiveGet exception + +## 2.2.0 (2019.08.16) + +### Added + +- Meaningful Jinja Template exception output handling + +### Fixed + +- Recursion in `sceptre_user_data` becoming infinite +- AWS `rate_exceeded` error when hitting AWS API too frequently +- Readme links +- StackGraph debugging output + +### Nonfunctional + +- Moved CircleCI Dockerfile to its own repository +- Add SonarQube analysis +- Change CircleCI setup to use context over environment variables +- Removed redundant test code +- Add badges to README +- Adjust Coverage fail-level to 92% +- Update CONTRIBUTING Guide ## 2.1.5 (2019.06.28) diff --git a/requirements/prod.txt b/requirements/prod.txt index 3e2dab356..3e1894eb7 100644 --- a/requirements/prod.txt +++ b/requirements/prod.txt @@ -4,3 +4,4 @@ colorama==0.3.9 Jinja2>=2.8,<3 networkx==2.1 PyYaml>=5.1,<6.0 +typing>=3.7,<3.8 diff --git a/sceptre/__init__.py b/sceptre/__init__.py index caf82efe6..99b6b0a81 100644 --- a/sceptre/__init__.py +++ b/sceptre/__init__.py @@ -6,7 +6,7 @@ __author__ = 'Cloudreach' __email__ = 'sceptre@cloudreach.com' -__version__ = '2.1.5' +__version__ = '2.2.1' # Set up logging to ``/dev/null`` like a library is supposed to. diff --git a/sceptre/connection_manager.py b/sceptre/connection_manager.py index ffe78fbfe..6b143ece4 100644 --- a/sceptre/connection_manager.py +++ b/sceptre/connection_manager.py @@ -55,8 +55,8 @@ def decorated(*args, **kwargs): time.sleep(mdelay) # Using De-correlated Jitter Algorithm - # We are picking number between a ceiling (delay_cap) of 45 seconds and the last - # delay multiplied by 2.5, rounding to two decimal places. + # We are picking number between a ceiling (delay_cap) of 45 seconds and the + # last delay multiplied by 2.5, rounding to two decimal places. mdelay = min(delay_cap, round((random.uniform(1, mdelay * 2.5)), 2)) attempts += 1 diff --git a/sceptre/resolvers/__init__.py b/sceptre/resolvers/__init__.py index 897ace858..846ee2076 100644 --- a/sceptre/resolvers/__init__.py +++ b/sceptre/resolvers/__init__.py @@ -2,6 +2,7 @@ import abc import logging from contextlib import contextmanager +from threading import RLock import six from sceptre.helpers import _call_func_on_values @@ -64,6 +65,7 @@ def __init__(self, name): self.name = "_" + name self.logger = logging.getLogger(__name__) self._get_in_progress = False + self._lock = RLock() def __get__(self, instance, type): """ @@ -73,7 +75,7 @@ def __get__(self, instance, type): :return: The attribute stored with the suffix ``name`` in the instance. :rtype: dict or list """ - with self._no_recursive_get(): + with self._lock, self._no_recursive_get(): def resolve(attr, key, value): try: attr[key] = value.resolve() @@ -97,8 +99,9 @@ def setup(attr, key, value): value.stack = instance value.setup() - _call_func_on_values(setup, value, Resolver) - setattr(instance, self.name, value) + with self._lock: + _call_func_on_values(setup, value, Resolver) + setattr(instance, self.name, value) class ResolveLater(object): """Represents a value that could not yet be resolved but can be resolved in the future.""" diff --git a/setup.cfg b/setup.cfg index 6750f5f21..b6f761ad9 100644 --- a/setup.cfg +++ b/setup.cfg @@ -1,5 +1,5 @@ [bumpversion] -current_version = 2.1.5 +current_version = 2.2.1 parse = (?P\d+)\.(?P\d+)\.(?P\d+)|(?P.*) commit = True tag = True diff --git a/setup.py b/setup.py index 1f1da85ff..57fc7a5d8 100755 --- a/setup.py +++ b/setup.py @@ -19,7 +19,8 @@ "colorama==0.3.9", "packaging==16.8", "six>=1.11.0,<2.0.0", - "networkx==2.1" + "networkx==2.1", + "typing>=3.7.0,<3.8.0" ] test_requirements = [