I've resisted writing this post for over a day because I was determined to find a solution from one of the many posts out there with answers to similar issues but none of them seem to work.
My issue...
When I run sam build && sam local invoke
, it works just fine. But, when I run a python -m pytest tests/ -v
, I get the following error.
Traceback:
../../../.pyenv/versions/3.8.6/lib/python3.8/importlib/__init__.py:127: in import_module
return _bootstrap._gcd_import(name[level:], package, level)
tests/unit/test_handler.py:3: in <module>
from get_devices import app
get_devices/app.py:4: in <module>
import aurora
E ModuleNotFoundError: No module named 'aurora'
The aurora module is one I wrote that allows me to connect with AWS Aurora. It's in a layer so I can share it across my various lambdas.
Here is what I've tried
I've added empty __init__.py
files. I've also tried adding setup.py and conftest.py to my root. I've tried playing around sys.path
and tirelessly tried importing my aurora module with relative and absolute paths to no avail. I found the sam-python-with-layers project but when I run pytest on it, I get the same error (just with different module name).
My question...
Is SAM or the combo of SAM + PyEnv preventing pytest from finding the aurora module? How can I get around this? Any assistance would be greatly appreciated.
Project/Code...
# project tree
├── __init__.py
├── get_devices
│ ├── __init__.py
│ ├── app.py
│ ├── requirements.txt
├── template.yaml
├── tests
│ ├── __init__.py
│ └── unit
│ ├── __init__.py
│ └── test_handler.py
└── utils_layer
├── __init__.py
├── python
│ ├── __init__.py
│ ├── aurora.py
│ ├── pg8000
This is my aurora.py file...
# aurora.py
import boto3
import os
import pg8000
import ssl
__location__ = os.path.realpath(os.path.join(os.getcwd(), os.path.dirname(__file__)))
def make_conn():
conn = None
try:
conn = pg8000.connect(
database=db_name,
user=db_user,
password=db_password,
host=db_host,
port=db_port,
ssl_context=ssl_context
)
except Exception as e:
print(f'Connection error: {e}')
return conn
This is my app.py where I import the aurora module...
# app.py
import aurora
def lambda_handler(event, context):
conn = aurora.make_conn()
if conn:
print('connected')
This is my template.yaml file...
# template.yaml
Globals:
Function:
Runtime: python3.8
MemorySize: 256
Timeout: 60
Layers:
- !Ref UtilsLayer
Resources:
GetDevicesFunction:
Type: AWS::Serverless::Function
Properties:
CodeUri: get_devices/
Handler: app.lambda_handler
Policies:
-
Version: '2012-10-17'
Statement:
Effect: Allow
Action: rds-db:connect
Resource: !FindInMap [ResourcesName, !Ref MyEnvironment, databaseResourceId]
Events:
GetDevicesApiEvent:
Type: Api
Properties:
Path: /devices
Method: GET
UtilsLayer:
Type: AWS::Serverless::LayerVersion
Properties:
Description: Utils layer
ContentUri: utils_layer/
CompatibleRuntimes:
- python3.8
RetentionPolicy: Delete