Metadata-Version: 2.3
Name: aiomoto
Version: 0.0.9
Summary: Moto-style AWS service mocks for aiobotocore/aioboto3
Keywords: aws,moto,aioboto3,aiobotocore,asyncio,testing,mocks
Author: Owen Lamont
Author-email: Owen Lamont <owenrlamont@gmail.com>
License: MIT License
         
         Copyright (c) 2025 Owen Lamont
         
         Permission is hereby granted, free of charge, to any person obtaining a copy
         of this software and associated documentation files (the "Software"), to deal
         in the Software without restriction, including without limitation the rights
         to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         copies of the Software, and to permit persons to whom the Software is
         furnished to do so, subject to the following conditions:
         
         The above copyright notice and this permission notice shall be included in all
         copies or substantial portions of the Software.
         
         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
         SOFTWARE.
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: Operating System :: OS Independent
Classifier: License :: OSI Approved :: MIT License
Classifier: Natural Language :: English
Classifier: Programming Language :: Python
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.10
Classifier: Programming Language :: Python :: 3.11
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Programming Language :: Python :: 3.14
Classifier: Programming Language :: Python :: Implementation :: CPython
Classifier: Programming Language :: Python :: Free Threading :: 3 - Stable
Classifier: Topic :: Software Development :: Libraries
Classifier: Topic :: Software Development :: Testing
Requires-Dist: aiobotocore>=2.24.1,<=2.25.1
Requires-Dist: moto>=5.1.5,<=5.1.17
Requires-Dist: moto[acm]>=5.1.5,<=5.1.17 ; extra == 'acm'
Requires-Dist: moto[acmpca]>=5.1.5,<=5.1.17 ; extra == 'acmpca'
Requires-Dist: moto[all]>=5.1.5,<=5.1.17 ; extra == 'all'
Requires-Dist: moto[amp]>=5.1.5,<=5.1.17 ; extra == 'amp'
Requires-Dist: moto[apigateway]>=5.1.5,<=5.1.17 ; extra == 'apigateway'
Requires-Dist: moto[apigatewayv2]>=5.1.5,<=5.1.17 ; extra == 'apigatewayv2'
Requires-Dist: moto[applicationautoscaling]>=5.1.5,<=5.1.17 ; extra == 'applicationautoscaling'
Requires-Dist: moto[appsync]>=5.1.5,<=5.1.17 ; extra == 'appsync'
Requires-Dist: moto[athena]>=5.1.5,<=5.1.17 ; extra == 'athena'
Requires-Dist: moto[autoscaling]>=5.1.5,<=5.1.17 ; extra == 'autoscaling'
Requires-Dist: moto[awslambda]>=5.1.5,<=5.1.17 ; extra == 'awslambda'
Requires-Dist: moto[awslambda-simple]>=5.1.5,<=5.1.17 ; extra == 'awslambda-simple'
Requires-Dist: moto[backup]>=5.1.5,<=5.1.17 ; extra == 'backup'
Requires-Dist: moto[batch]>=5.1.5,<=5.1.17 ; extra == 'batch'
Requires-Dist: moto[batch-simple]>=5.1.5,<=5.1.17 ; extra == 'batch-simple'
Requires-Dist: moto[budgets]>=5.1.5,<=5.1.17 ; extra == 'budgets'
Requires-Dist: moto[ce]>=5.1.5,<=5.1.17 ; extra == 'ce'
Requires-Dist: moto[cloudformation]>=5.1.5,<=5.1.17 ; extra == 'cloudformation'
Requires-Dist: moto[cloudfront]>=5.1.5,<=5.1.17 ; extra == 'cloudfront'
Requires-Dist: moto[cloudtrail]>=5.1.5,<=5.1.17 ; extra == 'cloudtrail'
Requires-Dist: moto[cloudwatch]>=5.1.5,<=5.1.17 ; extra == 'cloudwatch'
Requires-Dist: moto[codebuild]>=5.1.5,<=5.1.17 ; extra == 'codebuild'
Requires-Dist: moto[codecommit]>=5.1.5,<=5.1.17 ; extra == 'codecommit'
Requires-Dist: moto[codepipeline]>=5.1.5,<=5.1.17 ; extra == 'codepipeline'
Requires-Dist: moto[cognitoidentity]>=5.1.5,<=5.1.17 ; extra == 'cognitoidentity'
Requires-Dist: moto[cognitoidp]>=5.1.5,<=5.1.17 ; extra == 'cognitoidp'
Requires-Dist: moto[comprehend]>=5.1.5,<=5.1.17 ; extra == 'comprehend'
Requires-Dist: moto[config]>=5.1.5,<=5.1.17 ; extra == 'config'
Requires-Dist: moto[databrew]>=5.1.5,<=5.1.17 ; extra == 'databrew'
Requires-Dist: moto[datapipeline]>=5.1.5,<=5.1.17 ; extra == 'datapipeline'
Requires-Dist: moto[datasync]>=5.1.5,<=5.1.17 ; extra == 'datasync'
Requires-Dist: moto[dax]>=5.1.5,<=5.1.17 ; extra == 'dax'
Requires-Dist: moto[dms]>=5.1.5,<=5.1.17 ; extra == 'dms'
Requires-Dist: moto[ds]>=5.1.5,<=5.1.17 ; extra == 'ds'
Requires-Dist: moto[dynamodb]>=5.1.5,<=5.1.17 ; extra == 'dynamodb'
Requires-Dist: moto[dynamodbstreams]>=5.1.5,<=5.1.17 ; extra == 'dynamodbstreams'
Requires-Dist: moto[ebs]>=5.1.5,<=5.1.17 ; extra == 'ebs'
Requires-Dist: moto[ec2]>=5.1.5,<=5.1.17 ; extra == 'ec2'
Requires-Dist: moto[ec2instanceconnect]>=5.1.5,<=5.1.17 ; extra == 'ec2instanceconnect'
Requires-Dist: moto[ecr]>=5.1.5,<=5.1.17 ; extra == 'ecr'
Requires-Dist: moto[ecs]>=5.1.5,<=5.1.17 ; extra == 'ecs'
Requires-Dist: moto[efs]>=5.1.5,<=5.1.17 ; extra == 'efs'
Requires-Dist: moto[eks]>=5.1.5,<=5.1.17 ; extra == 'eks'
Requires-Dist: moto[elasticache]>=5.1.5,<=5.1.17 ; extra == 'elasticache'
Requires-Dist: moto[elasticbeanstalk]>=5.1.5,<=5.1.17 ; extra == 'elasticbeanstalk'
Requires-Dist: moto[elastictranscoder]>=5.1.5,<=5.1.17 ; extra == 'elastictranscoder'
Requires-Dist: moto[elb]>=5.1.5,<=5.1.17 ; extra == 'elb'
Requires-Dist: moto[elbv2]>=5.1.5,<=5.1.17 ; extra == 'elbv2'
Requires-Dist: moto[emr]>=5.1.5,<=5.1.17 ; extra == 'emr'
Requires-Dist: moto[emrcontainers]>=5.1.5,<=5.1.17 ; extra == 'emrcontainers'
Requires-Dist: moto[emrserverless]>=5.1.5,<=5.1.17 ; extra == 'emrserverless'
Requires-Dist: moto[es]>=5.1.5,<=5.1.17 ; extra == 'es'
Requires-Dist: moto[events]>=5.1.5,<=5.1.17 ; extra == 'events'
Requires-Dist: moto[firehose]>=5.1.5,<=5.1.17 ; extra == 'firehose'
Requires-Dist: moto[forecast]>=5.1.5,<=5.1.17 ; extra == 'forecast'
Requires-Dist: moto[glacier]>=5.1.5,<=5.1.17 ; extra == 'glacier'
Requires-Dist: moto[glue]>=5.1.5,<=5.1.17 ; extra == 'glue'
Requires-Dist: moto[greengrass]>=5.1.5,<=5.1.17 ; extra == 'greengrass'
Requires-Dist: moto[guardduty]>=5.1.5,<=5.1.17 ; extra == 'guardduty'
Requires-Dist: moto[iam]>=5.1.5,<=5.1.17 ; extra == 'iam'
Requires-Dist: moto[inspector2]>=5.1.5,<=5.1.17 ; extra == 'inspector2'
Requires-Dist: moto[iot]>=5.1.5,<=5.1.17 ; extra == 'iot'
Requires-Dist: moto[iotdata]>=5.1.5,<=5.1.17 ; extra == 'iotdata'
Requires-Dist: moto[ivs]>=5.1.5,<=5.1.17 ; extra == 'ivs'
Requires-Dist: moto[kinesis]>=5.1.5,<=5.1.17 ; extra == 'kinesis'
Requires-Dist: moto[kinesisvideo]>=5.1.5,<=5.1.17 ; extra == 'kinesisvideo'
Requires-Dist: moto[kinesisvideoarchivedmedia]>=5.1.5,<=5.1.17 ; extra == 'kinesisvideoarchivedmedia'
Requires-Dist: moto[kms]>=5.1.5,<=5.1.17 ; extra == 'kms'
Requires-Dist: moto[logs]>=5.1.5,<=5.1.17 ; extra == 'logs'
Requires-Dist: moto[managedblockchain]>=5.1.5,<=5.1.17 ; extra == 'managedblockchain'
Requires-Dist: moto[mediaconnect]>=5.1.5,<=5.1.17 ; extra == 'mediaconnect'
Requires-Dist: moto[medialive]>=5.1.5,<=5.1.17 ; extra == 'medialive'
Requires-Dist: moto[mediapackage]>=5.1.5,<=5.1.17 ; extra == 'mediapackage'
Requires-Dist: moto[mediastore]>=5.1.5,<=5.1.17 ; extra == 'mediastore'
Requires-Dist: moto[mediastoredata]>=5.1.5,<=5.1.17 ; extra == 'mediastoredata'
Requires-Dist: moto[meteringmarketplace]>=5.1.5,<=5.1.17 ; extra == 'meteringmarketplace'
Requires-Dist: moto[mq]>=5.1.5,<=5.1.17 ; extra == 'mq'
Requires-Dist: moto[opsworks]>=5.1.5,<=5.1.17 ; extra == 'opsworks'
Requires-Dist: moto[organizations]>=5.1.5,<=5.1.17 ; extra == 'organizations'
Requires-Dist: moto[panorama]>=5.1.5,<=5.1.17 ; extra == 'panorama'
Requires-Dist: moto[personalize]>=5.1.5,<=5.1.17 ; extra == 'personalize'
Requires-Dist: moto[pinpoint]>=5.1.5,<=5.1.17 ; extra == 'pinpoint'
Requires-Dist: moto[polly]>=5.1.5,<=5.1.17 ; extra == 'polly'
Requires-Dist: moto[proxy]>=5.1.5,<=5.1.17 ; extra == 'proxy'
Requires-Dist: moto[quicksight]>=5.1.5,<=5.1.17 ; extra == 'quicksight'
Requires-Dist: moto[ram]>=5.1.5,<=5.1.17 ; extra == 'ram'
Requires-Dist: moto[rds]>=5.1.5,<=5.1.17 ; extra == 'rds'
Requires-Dist: moto[redshift]>=5.1.5,<=5.1.17 ; extra == 'redshift'
Requires-Dist: moto[redshiftdata]>=5.1.5,<=5.1.17 ; extra == 'redshiftdata'
Requires-Dist: moto[rekognition]>=5.1.5,<=5.1.17 ; extra == 'rekognition'
Requires-Dist: moto[resourcegroups]>=5.1.5,<=5.1.17 ; extra == 'resourcegroups'
Requires-Dist: moto[resourcegroupstaggingapi]>=5.1.5,<=5.1.17 ; extra == 'resourcegroupstaggingapi'
Requires-Dist: moto[route53]>=5.1.5,<=5.1.17 ; extra == 'route53'
Requires-Dist: moto[route53resolver]>=5.1.5,<=5.1.17 ; extra == 'route53resolver'
Requires-Dist: moto[s3]>=5.1.5,<=5.1.17 ; extra == 's3'
Requires-Dist: moto[s3control]>=5.1.5,<=5.1.17 ; extra == 's3control'
Requires-Dist: moto[s3crc32c]>=5.1.5,<=5.1.17 ; extra == 's3crc32c'
Requires-Dist: moto[sagemaker]>=5.1.5,<=5.1.17 ; extra == 'sagemaker'
Requires-Dist: moto[scheduler]>=5.1.5,<=5.1.17 ; extra == 'scheduler'
Requires-Dist: moto[sdb]>=5.1.5,<=5.1.17 ; extra == 'sdb'
Requires-Dist: moto[secretsmanager]>=5.1.5,<=5.1.17 ; extra == 'secretsmanager'
Requires-Dist: moto[server]>=5.1.5,<=5.1.17 ; extra == 'server'
Requires-Dist: moto[servicediscovery]>=5.1.5,<=5.1.17 ; extra == 'servicediscovery'
Requires-Dist: moto[servicequotas]>=5.1.5,<=5.1.17 ; extra == 'servicequotas'
Requires-Dist: moto[ses]>=5.1.5,<=5.1.17 ; extra == 'ses'
Requires-Dist: moto[signer]>=5.1.5,<=5.1.17 ; extra == 'signer'
Requires-Dist: moto[sns]>=5.1.5,<=5.1.17 ; extra == 'sns'
Requires-Dist: moto[sqs]>=5.1.5,<=5.1.17 ; extra == 'sqs'
Requires-Dist: moto[ssm]>=5.1.5,<=5.1.17 ; extra == 'ssm'
Requires-Dist: moto[ssoadmin]>=5.1.5,<=5.1.17 ; extra == 'ssoadmin'
Requires-Dist: moto[stepfunctions]>=5.1.5,<=5.1.17 ; extra == 'stepfunctions'
Requires-Dist: moto[sts]>=5.1.5,<=5.1.17 ; extra == 'sts'
Requires-Dist: moto[support]>=5.1.5,<=5.1.17 ; extra == 'support'
Requires-Dist: moto[swf]>=5.1.5,<=5.1.17 ; extra == 'swf'
Requires-Dist: moto[textract]>=5.1.5,<=5.1.17 ; extra == 'textract'
Requires-Dist: moto[timestreamwrite]>=5.1.5,<=5.1.17 ; extra == 'timestreamwrite'
Requires-Dist: moto[transcribe]>=5.1.5,<=5.1.17 ; extra == 'transcribe'
Requires-Dist: moto[wafv2]>=5.1.5,<=5.1.17 ; extra == 'wafv2'
Requires-Dist: moto[xray]>=5.1.5,<=5.1.17 ; extra == 'xray'
Requires-Python: >=3.10
Project-URL: Issues, https://github.com/owenlamont/aiomoto/issues
Project-URL: Repository, https://github.com/owenlamont/aiomoto
Provides-Extra: acm
Provides-Extra: acmpca
Provides-Extra: all
Provides-Extra: amp
Provides-Extra: apigateway
Provides-Extra: apigatewayv2
Provides-Extra: applicationautoscaling
Provides-Extra: appsync
Provides-Extra: athena
Provides-Extra: autoscaling
Provides-Extra: awslambda
Provides-Extra: awslambda-simple
Provides-Extra: backup
Provides-Extra: batch
Provides-Extra: batch-simple
Provides-Extra: budgets
Provides-Extra: ce
Provides-Extra: cloudformation
Provides-Extra: cloudfront
Provides-Extra: cloudtrail
Provides-Extra: cloudwatch
Provides-Extra: codebuild
Provides-Extra: codecommit
Provides-Extra: codepipeline
Provides-Extra: cognitoidentity
Provides-Extra: cognitoidp
Provides-Extra: comprehend
Provides-Extra: config
Provides-Extra: databrew
Provides-Extra: datapipeline
Provides-Extra: datasync
Provides-Extra: dax
Provides-Extra: dms
Provides-Extra: ds
Provides-Extra: dynamodb
Provides-Extra: dynamodbstreams
Provides-Extra: ebs
Provides-Extra: ec2
Provides-Extra: ec2instanceconnect
Provides-Extra: ecr
Provides-Extra: ecs
Provides-Extra: efs
Provides-Extra: eks
Provides-Extra: elasticache
Provides-Extra: elasticbeanstalk
Provides-Extra: elastictranscoder
Provides-Extra: elb
Provides-Extra: elbv2
Provides-Extra: emr
Provides-Extra: emrcontainers
Provides-Extra: emrserverless
Provides-Extra: es
Provides-Extra: events
Provides-Extra: firehose
Provides-Extra: forecast
Provides-Extra: glacier
Provides-Extra: glue
Provides-Extra: greengrass
Provides-Extra: guardduty
Provides-Extra: iam
Provides-Extra: inspector2
Provides-Extra: iot
Provides-Extra: iotdata
Provides-Extra: ivs
Provides-Extra: kinesis
Provides-Extra: kinesisvideo
Provides-Extra: kinesisvideoarchivedmedia
Provides-Extra: kms
Provides-Extra: logs
Provides-Extra: managedblockchain
Provides-Extra: mediaconnect
Provides-Extra: medialive
Provides-Extra: mediapackage
Provides-Extra: mediastore
Provides-Extra: mediastoredata
Provides-Extra: meteringmarketplace
Provides-Extra: mq
Provides-Extra: opsworks
Provides-Extra: organizations
Provides-Extra: panorama
Provides-Extra: personalize
Provides-Extra: pinpoint
Provides-Extra: polly
Provides-Extra: proxy
Provides-Extra: quicksight
Provides-Extra: ram
Provides-Extra: rds
Provides-Extra: redshift
Provides-Extra: redshiftdata
Provides-Extra: rekognition
Provides-Extra: resourcegroups
Provides-Extra: resourcegroupstaggingapi
Provides-Extra: route53
Provides-Extra: route53resolver
Provides-Extra: s3
Provides-Extra: s3control
Provides-Extra: s3crc32c
Provides-Extra: sagemaker
Provides-Extra: scheduler
Provides-Extra: sdb
Provides-Extra: secretsmanager
Provides-Extra: server
Provides-Extra: servicediscovery
Provides-Extra: servicequotas
Provides-Extra: ses
Provides-Extra: signer
Provides-Extra: sns
Provides-Extra: sqs
Provides-Extra: ssm
Provides-Extra: ssoadmin
Provides-Extra: stepfunctions
Provides-Extra: sts
Provides-Extra: support
Provides-Extra: swf
Provides-Extra: textract
Provides-Extra: timestreamwrite
Provides-Extra: transcribe
Provides-Extra: wafv2
Provides-Extra: xray
Description-Content-Type: text/markdown

# aiomoto

`aiomoto` is Moto for aiobotocore / aioboto3 (while staying compatible with classic
botocore / boto3). It adapts Moto's stubber so async and sync clients share the same
in-memory backend: you can write to a mock S3 bucket with boto3 and read it back via
aiobotocore or aioboto3 in the same process.

## Supported today

- `mock_aws()` usable as `with` or `async with`, guarding against real HTTP requests.
- Actively exercised in tests: S3 (CRUD + listings + streaming reads), DynamoDB
  (create/describe/put/get), Secrets Manager, SES, SNS, SQS, KMS, STS, Lambda, Events,
  Kafka/MSK, and s3fs async integration — all sharing one Moto backend between sync
  boto3/botocore and async aiobotocore/aioboto3 clients.
- Other Moto services often work out of the box through the same patch layer; if you
  hit a service-specific gap, open an issue with a minimal repro so we can add a
  focused slice.

For the evolving project roadmap, see the wiki: <https://github.com/owenlamont/aiomoto/wiki/Roadmap>

## Motivation

Like many others I've wanted to use Moto with aiobotocore and aioboto3 but found that
wasn't supported, see:

- <https://github.com/getmoto/moto/issues/2039>
- <https://github.com/getmoto/moto/issues/8694>

The primary motivation for attempting to create an aiomoto repo came from this issue
<https://github.com/getmoto/moto/issues/8513>
which states aiobotocore support is out of scope for moto and the current primary moto
maintainer suggested creating an aiomoto repo.

## Related Work

<https://github.com/dazza-codes/pytest-aiomoto> was an earlier attempt at this but not
really maintained now.

There is discussion on aiobotocore repo about moto support here
<https://github.com/aio-libs/aiobotocore/discussions/1300>

Both the above approaches as far as I'm aware rely on the Moto's
[server mode](https://docs.getmoto.org/en/latest/docs/server_mode.html) which I don't
want to use (mainly as I found server mode was slower than other local AWS services
like dynamodb-local in-memory and I also wanted to run tests in parallel without
worrying about port clashes or race conditions). In short I don't want any server and I
want aiomoto to support the moto like mock contexts in the same thread / process as the
tests run in.

## Usage

Use `aiomoto.mock_aws` as a drop-in replacement for Moto's `mock_aws` that works
with both synchronous boto3/botocore clients and asynchronous aiobotocore/aioboto3
clients in the same process. It supports `with` and `async with` (and can decorate
sync/async callables).

### Use as a decorator

Use `@mock_aws` as a decorator when you want Moto started/stopped for the span of
a test function. Both sync and async callables are supported; omit parentheses
when you are not passing arguments (they remain optional to match Moto’s examples).
`mock_aws_decorator`
is also exported for teams that prefer an explicitly decorator-only name (or want
to preconfigure `reset` / `remove_data` once and reuse it) while leaving `mock_aws`
for context-manager usage.

```python
import boto3
from aiobotocore.session import AioSession
from aiomoto import mock_aws, mock_aws_decorator


@mock_aws
def test_sync_bucket() -> None:
    client = boto3.client("s3", region_name="us-east-1")
    client.create_bucket(Bucket="decorator-demo")


@mock_aws_decorator
async def test_async_bucket() -> None:
    async with AioSession().create_client("s3", region_name="us-east-1") as client:
        await client.create_bucket(Bucket="decorator-demo")
```

### Use as a context manager

```python
import boto3
from aiobotocore.session import AioSession
from aiomoto import mock_aws

async def demo():
    async with mock_aws():
        s3_sync = boto3.client("s3", region_name="us-east-1")
        s3_sync.create_bucket(Bucket="example")

        session = AioSession()
        async with session.create_client("s3", region_name="us-east-1") as s3_async:
            result = await s3_async.list_buckets()
            assert any(b["Name"] == "example" for b in result["Buckets"])
```

While aiomoto is active it prevents aiobotocore from issuing real HTTP calls; any
attempts fall back to Moto and will raise if they escape the stubber. Avoid mixing
raw Moto decorators with aiomoto contexts in the same test to keep state aligned.

> aiomoto supports Moto’s **in-process** mode only. Moto server/proxy modes
> (`TEST_SERVER_MODE`, proxy mode) will raise at `mock_aws()` time so you don’t
> accidentally depend on real network calls.

### s3fs (async) example

s3fs caches each `S3FileSystem` (unless `cacheable=False`) and installs a weakref
finalizer that calls `close_session` on the loop captured at construction time.
If that loop is already closed when the finalizer runs—e.g., pytest ends the
session loop while a cached instance still lives—you can see ``Event loop is
closed`` or “attached to a different loop” errors during teardown. Upstream switched to
`get_running_loop` in 2025.3.1 to reduce this, but explicit close is still safest.

```python
import asyncio
import aiobotocore.session
import pytest
import s3fs

from aiomoto import mock_aws


@pytest.mark.asyncio
async def test_s3fs_async_usage() -> None:
    session = aiobotocore.session.AioSession()
    fs = s3fs.S3FileSystem(asynchronous=True, session=session)

    try:
        with mock_aws():
            await fs._call_s3("create_bucket", Bucket="bucket-123")
            await fs._call_s3(
                "put_object", Bucket="bucket-123", Key="test.txt", Body=b"hi"
            )
            assert await fs._cat_file("bucket-123/test.txt") == b"hi"
    finally:
        if fs._s3 is not None:
            await fs._s3.close()
```

### DynamoDB example

```python
import boto3
from aiobotocore.session import AioSession
from aiomoto import mock_aws

AWS_REGION = "us-west-2"

async def demo():
    with mock_aws():
        # Sync write
        ddb_sync = boto3.client("dynamodb", region_name=AWS_REGION)
        ddb_sync.create_table(
            TableName="items",
            KeySchema=[{"AttributeName": "pk", "KeyType": "HASH"}],
            AttributeDefinitions=[{"AttributeName": "pk", "AttributeType": "S"}],
            BillingMode="PAY_PER_REQUEST",
        )
        ddb_sync.put_item(TableName="items", Item={"pk": {"S": "from-sync"}})

        # Async read (aiobotocore)
        async with AioSession().create_client(
            "dynamodb", region_name=AWS_REGION
        ) as ddb_async:
            item = await ddb_async.get_item(
                TableName="items", Key={"pk": {"S": "from-sync"}}
            )
            assert item["Item"]["pk"]["S"] == "from-sync"
```

## Roadmap

The living roadmap sits in the wiki [Roadmap](https://github.com/owenlamont/aiomoto/wiki/Roadmap)

## Limitations

- Mixing raw Moto decorators with `aiomoto.mock_aws` in the same test is unsupported;
  the contexts manage shared state differently and can diverge.
- aiomoto wraps moto and patches aiobotocore; aioboto3 and s3fs should be covered
  automatically as they use aiobotocore clients/resources.
- We keep version ranges narrow and tested together, if you notice a new version of
  aiobotocore or moto that doesn't get covered feel free to raise an issue for this.
