diff --git a/CHANGELOG.md b/CHANGELOG.md index 249d12c6d..10d067f98 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,9 @@ # Zappa Changelog -## next +## 0.52.0 +* Remove dateutil version restriction +* Fix failed downloads of wheel packages with non-alphanumeric characters +* Last release from Miserlou/Zappa * Removed references to zappa.io ## 0.51.0 diff --git a/zappa/__init__.py b/zappa/__init__.py index 2a1d400bc..c0fe60dd3 100644 --- a/zappa/__init__.py +++ b/zappa/__init__.py @@ -8,4 +8,4 @@ 'Zappa (and AWS Lambda) support the following versions of Python: {}'.format(formatted_supported_versions)) raise RuntimeError(err_msg) -__version__ = '0.51.0' +__version__ = '0.52.0' diff --git a/zappa/cli.py b/zappa/cli.py index 2820eacba..6a410818a 100755 --- a/zappa/cli.py +++ b/zappa/cli.py @@ -2122,7 +2122,8 @@ def load_settings(self, settings_file=None, session=None): runtime=self.runtime, tags=self.tags, endpoint_urls=self.stage_config.get('aws_endpoint_urls',{}), - xray_tracing=self.xray_tracing + xray_tracing=self.xray_tracing, + no_venv=self.vargs.get("no_venv") if self.vargs else None ) for setting in CUSTOM_SETTINGS: diff --git a/zappa/core.py b/zappa/core.py index 2798ae786..6746958d8 100644 --- a/zappa/core.py +++ b/zappa/core.py @@ -250,7 +250,8 @@ def __init__(self, runtime='python3.6', # Detected at runtime in CLI tags=(), endpoint_urls={}, - xray_tracing=False + xray_tracing=False, + no_venv=False ): """ Instantiate this new Zappa instance, loading any custom credentials if necessary. @@ -289,6 +290,7 @@ def __init__(self, self.endpoint_urls = endpoint_urls self.xray_tracing = xray_tracing + self.no_venv = no_venv # Some common invocations, such as DB migrations, # can take longer than the default. @@ -522,34 +524,37 @@ def create_lambda_zip( self, if not 'concurrent' in exclude: exclude.append('concurrent') - def splitpath(path): - parts = [] - (path, tail) = os.path.split(path) - while path and tail: - parts.append(tail) + to_exclude = [] + if not self.no_venv: + def splitpath(path): + parts = [] (path, tail) = os.path.split(path) - parts.append(os.path.join(path, tail)) - return list(map(os.path.normpath, parts))[::-1] - split_venv = splitpath(venv) - split_cwd = splitpath(cwd) - - # Ideally this should be avoided automatically, - # but this serves as an okay stop-gap measure. - if split_venv[-1] == split_cwd[-1]: # pragma: no cover - print( - "Warning! Your project and virtualenv have the same name! You may want " - "to re-create your venv with a new name, or explicitly define a " - "'project_name', as this may cause errors." - ) + while path and tail: + parts.append(tail) + (path, tail) = os.path.split(path) + parts.append(os.path.join(path, tail)) + return list(map(os.path.normpath, parts))[::-1] + split_venv = splitpath(venv) + split_cwd = splitpath(cwd) + + # Ideally this should be avoided automatically, + # but this serves as an okay stop-gap measure. + if split_venv[-1] == split_cwd[-1]: # pragma: no cover + print( + "Warning! Your project and virtualenv have the same name! You may want " + "to re-create your venv with a new name, or explicitly define a " + "'project_name', as this may cause errors." + ) + to_exclude = [split_venv[-1]] # First, do the project.. - temp_project_path = tempfile.mkdtemp(prefix='zappa-project') + temp_project_path = tempfile.mkdtemp(prefix='zappa-project') if not slim_handler: # Slim handler does not take the project files. if minify: # Related: https://github.com/Miserlou/Zappa/issues/744 - excludes = ZIP_EXCLUDES + exclude + [split_venv[-1]] + excludes = ZIP_EXCLUDES + exclude + to_exclude copytree(cwd, temp_project_path, metadata=False, symlinks=False, ignore=shutil.ignore_patterns(*excludes)) else: copytree(cwd, temp_project_path, metadata=False, symlinks=False) diff --git a/zappa/handler.py b/zappa/handler.py index 78a31cfda..944e5c326 100644 --- a/zappa/handler.py +++ b/zappa/handler.py @@ -549,13 +549,28 @@ def handler(self, event, context): zappa_returndict.setdefault('statusDescription', response.status) if response.data: - if settings.BINARY_SUPPORT and \ - not response.mimetype.startswith("text/") \ - and response.mimetype != "application/json": - zappa_returndict['body'] = base64.b64encode(response.data).decode('utf-8') - zappa_returndict["isBase64Encoded"] = True + content_encoding = response.headers.get("Content-Encoding", None) + binary_encodings = ("gzip", "compress", "deflate", "br") + if settings.BINARY_SUPPORT and content_encoding in binary_encodings: + try: + zappa_returndict["body"] = base64.b64encode(response.data).decode("utf8") + zappa_returndict["isBase64Encoded"] = True + except UnicodeDecodeError as e: + logger.exception(e) + logger.error(f"Unable to decode resulting base64 encoded response.data as 'utf8': response.data={response.data}") + logger.warning("Using response.get_data(as_text=True)") + zappa_returndict["body"] = response.get_data(as_text=True) else: - zappa_returndict['body'] = response.get_data(as_text=True) + try: + zappa_returndict["body"] = response.get_data(as_text=True) + except UnicodeDecodeError: + # If data can't be decoded as utf-8, try processing as binary + logger.warning( + "UnicodeDecodeError on response.get_data(as_text=True), " + "unable to decode response.data as 'utf8': encoding as base64 isBase64Encoded=True" + ) + zappa_returndict["body"] = base64.b64encode(response.data).decode("utf8") + zappa_returndict["isBase64Encoded"] = True zappa_returndict['statusCode'] = response.status_code if 'headers' in event: