# -*- coding: utf-8 -*-"""PynamoDB Context Manager for Using Specific Boto3 SessionsThis module provides a context manager that allows PynamoDB models to temporarilyuse different AWS credentials/sessions without modifying the model definition.This is particularly useful for:- Multi-account operations- Different AWS profiles for different environments- Temporary credential switching- Cross-account DynamoDB operations"""importtypingasTimportcontextlibimportbotocore.exceptionsfrompynamodb.connectionimportConnectionfrompynamodb.exceptionsimportPynamoDBExceptionifT.TYPE_CHECKING:# pragma: no coverfromboto_session_managerimportBotoSesManagerfrompynamodb.modelsimportModel
[docs]@contextlib.contextmanagerdefuse_boto_session(table:T.Type["Model"],bsm:T.Optional["BotoSesManager"]=None,restore_on_exit:bool=True,):""" Context manager to temporarily switch PynamoDB model to use different AWS credentials. This context manager allows a PynamoDB model to temporarily use different AWS credentials by leveraging the boto-session-manager's awscli() context manager and manipulating the model's connection and region settings. :param table: The PynamoDB model class that will use the new credentials. :param bsm: The boto session manager instance containing the target AWS credentials/profile to use. If None, the context manager has no effect, providing a clean API where users can conditionally switch credentials without separate if/else logic. See https://pypi.org/project/boto-session-manager/ :param restore_on_exit: If True, restore original connection on exit if False, keep current connection for subsequent operations. See also :func:`reset_connection`. :yields: None, This is a context manager that doesn't return a value Usage:: # Define your model class MyModel(Model): class Meta: table_name = "my_table" region = "us-east-1" id = NumberAttribute(hash_key=True) # Use different credentials temporarily target_bsm = BotoSesManager(profile_name="target_profile") with target_aws_cred(target_bsm, MyModel): # All operations here use the target_profile credentials MyModel.create_table() item = MyModel(id=1) item.save() # Back to original credentials items = MyModel.scan() # This uses default credentials How it works: 1. Saves the current region setting from the model's Meta class 2. Enters the boto session manager's awscli() context (sets env vars) 3. Clears the model's cached connection to force recreation 4. Updates the model's region to match the session manager's region 5. Creates a new Connection object with the new region 6. On exit, restores the original region and clears connection again .. note:: - The model's _connection attribute is set to None to force PynamoDB to create a new connection with the current environment variables - The region is temporarily changed to ensure consistency with the session - All changes are reverted when exiting the context manager when restore_on_exit is True """# Store the current region setting to restore it latercurrent_aws_region=table.Meta.regiontry:ifbsmisNone:# if BotoSesManager is not provided, we do nothingyieldNoneelse:# Enter the boto session manager's context# This typically sets AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, etc. as env varswithbsm.awscli():# Clear the existing connection to force PynamoDB to create a new one# with the current environment variables (which are now set by bsm.awscli())table._connection=None# Update the model's region to match the session manager's region# This ensures consistency between the session and the model configurationtable.Meta.region=bsm.aws_region# Create a new connection object with the new region# This connection will inherit the AWS credentials from environment variablesConnection(region=bsm.aws_region)# Yield control back to the caller# All PynamoDB operations within this context will use the new credentialsyieldNonefinally:ifrestore_on_exitand(bsmisnotNone):# Cleanup: Restore the original state regardless of success or failure# Clear the connection again to ensure clean statetable._connection=None# Restore the original region settingtable.Meta.region=current_aws_region# Create a new connection with the original region# When the bsm.awscli() context exits, the environment variables# will be restored, so this connection will use the original credentialsConnection(region=current_aws_region)
[docs]defreset_connection(table:T.Type["Model"],):""" Reset the PynamoDB model's connection to use the default AWS connection. This is useful when you have changed AWS credentials using :func:`use_boto_session` context manager, and then want to revert back to the default PynamoDB behavior. :param table: The PynamoDB model class whose connection should be reset. Usage:: # Define your model class MyModel(Model): ... # Use different credentials and keep the connection with use_boto_session(target_bsm, MyModel, restore_on_exit=False): ... # Reset the connection to use the default AWS credentials reset_connection(MyModel) """# Clear the existing connection then make an test API call to force# PynamoDB to create a new onetable._connection=Nonetry:table.describe_table()exceptPynamoDBException:# pragma: no coverpassexceptbotocore.exceptions.ClientError:# pragma: no coverpass