Description
What were you trying to accomplish?
We're trying to use the batch utility to process SQS records. We're using Pydantic for various things, including the messages pushed into SQS. If we've imported pydantic before importing aws_lambda_powertools.utilities.batch
we hit an exception due to email-validator
not being installed.
We're not using pydantic's EmailStr
, and so haven't installed email-validator
and would prefer not to if possible. (NB. email-validator itself is small (< 100K), but it seems to require dnspython
which is almost 2MB.)
Expected Behavior
Using batch classes shouldn't require email-validator
to be installed, even if Pydantic has already been imported.
Current Behavior
Traceback (most recent call last):
File "pydantic/networks.py", line 409, in pydantic.networks.import_email_validator
ModuleNotFoundError: No module named 'email_validator'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<string>", line 1, in <module>
File ".../site-packages/aws_lambda_powertools/utilities/batch/__init__.py", line 7, in <module>
from aws_lambda_powertools.utilities.batch.base import (
File ".../site-packages/aws_lambda_powertools/utilities/batch/base.py", line 36, in <module>
from aws_lambda_powertools.utilities.parser.models import DynamoDBStreamRecordModel
File ".../site-packages/aws_lambda_powertools/utilities/parser/__init__.py", line 3, in <module>
from . import envelopes
File ".../site-packages/aws_lambda_powertools/utilities/parser/envelopes/__init__.py", line 1, in <module>
from .apigw import ApiGatewayEnvelope
File ".../site-packages/aws_lambda_powertools/utilities/parser/envelopes/apigw.py", line 4, in <module>
from ..models import APIGatewayProxyEventModel
File ".../site-packages/aws_lambda_powertools/utilities/parser/models/__init__.py", line 32, in <module>
from .ses import (
File ".../site-packages/aws_lambda_powertools/utilities/parser/models/ses.py", line 21, in <module>
class SesReceipt(BaseModel):
File "pydantic/main.py", line 204, in pydantic.main.ModelMetaclass.__new__
File "pydantic/fields.py", line 488, in pydantic.fields.ModelField.infer
File "pydantic/fields.py", line 419, in pydantic.fields.ModelField.__init__
File "pydantic/fields.py", line 534, in pydantic.fields.ModelField.prepare
File "pydantic/fields.py", line 728, in pydantic.fields.ModelField._type_analysis
File "pydantic/fields.py", line 778, in pydantic.fields.ModelField._create_sub_type
File "pydantic/fields.py", line 419, in pydantic.fields.ModelField.__init__
File "pydantic/fields.py", line 539, in pydantic.fields.ModelField.prepare
File "pydantic/fields.py", line 801, in pydantic.fields.ModelField.populate_validators
File "pydantic/networks.py", line 422, in __get_validators__
File "pydantic/networks.py", line 411, in pydantic.networks.import_email_validator
ImportError: email-validator is not installed, run `pip install pydantic[email]`
Possible Solution
- A minimal quick fix would be to expand the dynamic "has_pydantic" check to look for
email_validator
too, although this worsens the user/typing experience for those who are using pydantic without email validation - A targeted fix might be to break up the modules to reduce the flow-on consequences of a single import statement, for instance,
batch
could importDynamoDBStreamRecordModel
(etc) in a way that doesn't trigger also importenvelopes
, orenvelopes/apigw.py
could importAPIGatewayProxyEventModel
in a way that doesn't importses
- A more general fix might be to adjust
ses
(etc):
- make it conditional on
email-validator
: if email-validator doesn't exist, then the models don't function, in some way that has a useful error message - (silently) fall back to
str
instead ofEmailStr
, if email-validator isn't installed
(Either of the last two would potentially also resolve the related issue that it is impossible to use aws_lambda_powertools.utilities.parser
without email-validator, even if avoiding the SES models. See python -c 'import aws_lambda_powertools.utilities.parser'
.)
Steps to Reproduce (for bugs)
pip install aws-lambda-powertools==1.24.2 aws-xray-sdk==2.9.0 boto3==1.20.48 botocore==1.23.48 fastjsonschema==2.15.3 future==0.18.2 jmespath==0.10.0 pydantic==1.9.0 python-dateutil==2.8.2 s3transfer==0.5.1 six==1.16.0 typing_extensions==4.0.1 urllib3==1.26.8 wrapt==1.13.3
python -c 'import pydantic; from aws_lambda_powertools.utilities import batch'
Note: removing the import pydantic;
works fine, since the check is just based on whether pydantic has been imported, not whether it is importable.
Environment
- Powertools version used: 1.24.2 (full freeze output in
pip
command above) - Packaging format (Layers, PyPi): N/A
- AWS Lambda function runtime: N/A
- Debugging logs N/A