Repository: localstack/localstack

Issue:
Installation question -- Localstack start error: cannot import name requests
trying to install localstack with pip(pip2) and python 2.7
* OS: ubuntu 18.04 LTS 
* verify python:  python --version   ====> Output: Python 2.7.15+
* verify python location: whereis python ===> python: /usr/bin/python2.7-config /usr/bin/python /usr/bin/python3.6m /usr/bin/python3.6 /usr/bin/python2.7 /usr/lib/python3.7 /usr/lib/python3.6 /usr/lib/python2.7 /etc/python /etc/python3.6 /etc/python2.7 /usr/local/lib/python3.6 /usr/local/lib/python2.7 /usr/include/python3.6m /usr/include/python2.7 /usr/share/python /usr/share/man/man1/python.1.gz

* ls -l /usr/bin/python ====> lrwxrwxrwx 1 root root 9 Apr 16  2018 /usr/bin/python -> python2.7
* check PATH: echo $PATH ====> OTHERPATH:/usr/bin:OTHERPATH

* check pip:  pip --version ====> pip 9.0.1 from /usr/lib/python2.7/dist-packages (python 2.7)
* check pip bin PATH: whereis pip ====> pip: /usr/bin/pip
* pip3 is not installed.

[install.log](https://github.com/localstack/localstack/files/3843879/install.log)

* check localstack install status: pip list ====> localstack (0.10.5)
localstack-client (0.15)
localstack-ext (0.10.59)

* check docker version: docker --version
Docker version 19.03.1, build 74b1e89


* start localstack:   localstack start ====>
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
/usr/share/python-wheels/requests-2.18.4-py2.py3-none-any.whl/requests/__init__.py:80: RequestsDependencyWarning: urllib3 (1.25.7) or chardet (3.0.4) doesn't match a supported version!
Traceback (most recent call last):
  File "/home/jguo/.local/bin/localstack", line 35, in <module>
    from localstack.utils import cli, bootstrap
  File "/home/jguo/.local/lib/python2.7/site-packages/localstack/utils/cli.py", line 3, in <module>
    from localstack.utils.bootstrap import (
  File "/home/jguo/.local/lib/python2.7/site-packages/localstack/utils/bootstrap.py", line 11, in <module>
    import pip as pip_mod
  File "/usr/lib/python2.7/dist-packages/pip/__init__.py", line 31, in <module>
    from pip.vcs import git, mercurial, subversion, bazaar  # noqa
  File "/usr/lib/python2.7/dist-packages/pip/vcs/mercurial.py", line 9, in <module>
    from pip.download import path_to_url
  File "/usr/lib/python2.7/dist-packages/pip/download.py", line 40, in <module>
    from pip._vendor import requests, six
ImportError: cannot import name requests




<!-- Love localstack? Please consider supporting our collective:
👉  https://opencollective.com/localstack/donate -->


Discussion:

Resolving patch:
diff --git a/localstack/services/awslambda/lambda_executors.py b/localstack/services/awslambda/lambda_executors.py
--- a/localstack/services/awslambda/lambda_executors.py
+++ b/localstack/services/awslambda/lambda_executors.py
@@ -328,7 +328,7 @@ def prime_docker_container(self, runtime, func_arn, env_vars, lambda_cwd):
             status = self.get_docker_container_status(func_arn)
             LOG.debug('Priming docker container (status "%s"): %s' % (status, container_name))
 
-            lambda_container_registry = config.LAMBDA_CONTAINER_REGISTRY
+            docker_image = Util.docker_image_for_runtime(runtime)
 
             # Container is not running or doesn't exist.
             if status < 1:
@@ -358,9 +358,8 @@ def prime_docker_container(self, runtime, func_arn, env_vars, lambda_cwd):
                     ' -e LOCALSTACK_HOSTNAME="$LOCALSTACK_HOSTNAME"'
                     '  %s'  # env_vars
                     '  %s'  # network
-                    ' %s:%s'
-                ) % (docker_cmd, container_name, mount_volume_str, env_vars_str, network_str,
-                     lambda_container_registry, runtime)
+                    ' %s'
+                ) % (docker_cmd, container_name, mount_volume_str, env_vars_str, network_str, docker_image)
                 LOG.debug(cmd)
                 run(cmd)
 
@@ -381,12 +380,12 @@ def prime_docker_container(self, runtime, func_arn, env_vars, lambda_cwd):
                 time.sleep(1)
 
             # Get the entry point for the image.
-            LOG.debug('Getting the entrypoint for image: %s:%s' % (lambda_container_registry, runtime))
+            LOG.debug('Getting the entrypoint for image: %s' % (docker_image))
             cmd = (
                 '%s image inspect'
                 ' --format="{{ .ContainerConfig.Entrypoint }}"'
-                ' %s:%s'
-            ) % (docker_cmd, lambda_container_registry, runtime)
+                ' %s'
+            ) % (docker_cmd, docker_image)
 
             LOG.debug(cmd)
             run_result = run(cmd)
@@ -586,7 +585,7 @@ def prepare_execution(self, func_arn, env_vars, runtime, command, handler, lambd
         network = config.LAMBDA_DOCKER_NETWORK
         network_str = '--network="%s"' % network if network else ''
         docker_cmd = self._docker_cmd()
-        lambda_container_registry = config.LAMBDA_CONTAINER_REGISTRY
+        docker_image = Util.docker_image_for_runtime(runtime)
 
         if config.LAMBDA_REMOTE_DOCKER:
             cmd = (
@@ -596,12 +595,12 @@ def prepare_execution(self, func_arn, env_vars, runtime, command, handler, lambd
                 ' %s'
                 ' %s'  # network
                 ' --rm'
-                ' "%s:%s" %s'
+                ' %s %s'
                 ')";'
                 '%s cp "%s/." "$CONTAINER_ID:/var/task"; '
                 '%s start -ai "$CONTAINER_ID";'
             ) % (docker_cmd, entrypoint, debug_docker_java_port, env_vars_string, network_str,
-                 lambda_container_registry, runtime, command,
+                 docker_image, command,
                  docker_cmd, lambda_cwd,
                  docker_cmd)
         else:
@@ -612,9 +611,9 @@ def prepare_execution(self, func_arn, env_vars, runtime, command, handler, lambd
                 ' %s'
                 ' %s'  # network
                 ' --rm'
-                ' "%s:%s" %s'
-            ) % (docker_cmd, entrypoint, lambda_cwd_on_host, env_vars_string, network_str,
-                 lambda_container_registry, runtime, command)
+                ' %s %s'
+            ) % (docker_cmd, entrypoint, lambda_cwd_on_host, env_vars_string,
+                 network_str, docker_image, command)
         return cmd
 
 
@@ -679,6 +678,16 @@ def get_host_path_for_path_in_docker(cls, path):
         return re.sub(r'^%s/(.*)$' % config.TMP_FOLDER,
                       r'%s/\1' % config.HOST_TMP_FOLDER, path)
 
+    @classmethod
+    def docker_image_for_runtime(cls, runtime):
+        docker_tag = runtime
+        docker_image = config.LAMBDA_CONTAINER_REGISTRY
+        # TODO: remove prefix once execution issues are fixed with dotnetcore/python lambdas
+        # See https://github.com/lambci/docker-lambda/pull/218
+        if docker_image == 'lambci/lambda':
+            docker_tag = '20191117-%s' % docker_tag
+        return '"%s:%s"' % (docker_image, docker_tag)
+
 
 # --------------
 # GLOBAL STATE
diff --git a/localstack/services/dynamodb/dynamodb_listener.py b/localstack/services/dynamodb/dynamodb_listener.py
--- a/localstack/services/dynamodb/dynamodb_listener.py
+++ b/localstack/services/dynamodb/dynamodb_listener.py
@@ -41,6 +41,8 @@ def forward_request(self, method, path, data, headers):
         if random.random() < config.DYNAMODB_ERROR_PROBABILITY:
             return error_response_throughput()
 
+        ProxyListenerDynamoDB.thread_local.existing_item = None
+
         action = headers.get('X-Amz-Target')
         if action == '%s.CreateTable' % ACTION_PREFIX:
             # Check if table exists, to avoid error log output from DynamoDBLocal
@@ -50,23 +52,22 @@ def forward_request(self, method, path, data, headers):
         elif action in ('%s.PutItem' % ACTION_PREFIX, '%s.UpdateItem' % ACTION_PREFIX, '%s.DeleteItem' % ACTION_PREFIX):
             # find an existing item and store it in a thread-local, so we can access it in return_response,
             # in order to determine whether an item already existed (MODIFY) or not (INSERT)
-            ProxyListenerDynamoDB.thread_local.existing_item = find_existing_item(data)
+            try:
+                ProxyListenerDynamoDB.thread_local.existing_item = find_existing_item(data)
+            except Exception as e:
+                if 'ResourceNotFoundException' in str(e):
+                    return get_table_not_found_error()
+                raise
         elif action == '%s.DescribeTable' % ACTION_PREFIX:
             # Check if table exists, to avoid error log output from DynamoDBLocal
             table_names = ddb_client.list_tables()['TableNames']
             if to_str(data['TableName']) not in table_names:
-                response = error_response(message='Cannot do operations on a non-existent table',
-                                          error_type='ResourceNotFoundException')
-                fix_headers_for_updated_response(response)
-                return response
+                return get_table_not_found_error()
         elif action == '%s.DeleteTable' % ACTION_PREFIX:
             # Check if table exists, to avoid error log output from DynamoDBLocal
             table_names = ddb_client.list_tables()['TableNames']
             if to_str(data['TableName']) not in table_names:
-                response = error_response(message='Cannot do operations on a non-existent table',
-                                          error_type='ResourceNotFoundException')
-                fix_headers_for_updated_response(response)
-                return response
+                return get_table_not_found_error()
         elif action == '%s.BatchWriteItem' % ACTION_PREFIX:
             existing_items = []
             for table_name in sorted(data['RequestItems'].keys()):
@@ -363,6 +364,13 @@ def find_existing_item(put_item, table_name=None):
     return existing_item.get('Item')
 
 
+def get_table_not_found_error():
+    response = error_response(message='Cannot do operations on a non-existent table',
+                              error_type='ResourceNotFoundException')
+    fix_headers_for_updated_response(response)
+    return response
+
+
 def fix_headers_for_updated_response(response):
     response.headers['content-length'] = len(to_bytes(response.content))
     response.headers['x-amz-crc32'] = calculate_crc32(response)
diff --git a/localstack/utils/common.py b/localstack/utils/common.py
--- a/localstack/utils/common.py
+++ b/localstack/utils/common.py
@@ -13,6 +13,7 @@
 import logging
 import zipfile
 import binascii
+import calendar
 import tempfile
 import threading
 import subprocess
@@ -485,7 +486,7 @@ def now():
 
 
 def mktime(timestamp):
-    return time.mktime(timestamp.timetuple())
+    return calendar.timegm(timestamp.timetuple())
 
 
 def mkdir(folder):


Test patch: