aws-expect 0.1.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1 @@
1
+ * @PhishStick-hub
@@ -0,0 +1,92 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - main
7
+ - develop
8
+ workflow_dispatch:
9
+
10
+ jobs:
11
+ quality-checks:
12
+ name: Quality Checks
13
+ runs-on: ubuntu-latest
14
+ steps:
15
+ - name: Checkout code
16
+ uses: actions/checkout@v4
17
+
18
+ - name: Install uv
19
+ uses: astral-sh/setup-uv@v4
20
+ with:
21
+ enable-cache: true
22
+
23
+ - name: Set up Python
24
+ uses: actions/setup-python@v5
25
+ with:
26
+ python-version: "3.13"
27
+
28
+ - name: Install dependencies
29
+ run: uv sync --all-groups
30
+
31
+ - name: Check formatting with ruff
32
+ run: uv run ruff format --check .
33
+
34
+ - name: Lint with ruff
35
+ run: uv run ruff check .
36
+
37
+ - name: Type check with ty
38
+ run: uv run ty check
39
+
40
+ test:
41
+ name: Test Suite
42
+ runs-on: ubuntu-latest
43
+ steps:
44
+ - name: Checkout code
45
+ uses: actions/checkout@v4
46
+
47
+ - name: Install uv
48
+ uses: astral-sh/setup-uv@v4
49
+ with:
50
+ enable-cache: true
51
+
52
+ - name: Set up Python
53
+ uses: actions/setup-python@v5
54
+ with:
55
+ python-version: "3.13"
56
+
57
+ - name: Install dependencies
58
+ run: uv sync --all-groups
59
+
60
+ - name: Run tests
61
+ run: uv run pytest tests/ -v
62
+
63
+ build:
64
+ name: Build Package
65
+ runs-on: ubuntu-latest
66
+ needs: [quality-checks, test]
67
+ steps:
68
+ - name: Checkout code
69
+ uses: actions/checkout@v4
70
+
71
+ - name: Install uv
72
+ uses: astral-sh/setup-uv@v4
73
+ with:
74
+ enable-cache: true
75
+
76
+ - name: Set up Python
77
+ uses: actions/setup-python@v5
78
+ with:
79
+ python-version: "3.13"
80
+
81
+ - name: Install dependencies
82
+ run: uv sync --all-groups
83
+
84
+ - name: Build package
85
+ run: uv build
86
+
87
+ - name: Upload build artifacts
88
+ uses: actions/upload-artifact@v4
89
+ with:
90
+ name: dist
91
+ path: dist/
92
+ retention-days: 7
@@ -0,0 +1,59 @@
1
+ name: PR Checks
2
+
3
+ on:
4
+ pull_request:
5
+ branches:
6
+ - main
7
+
8
+ jobs:
9
+ quality-checks:
10
+ name: Quick Quality Checks
11
+ runs-on: ubuntu-latest
12
+ steps:
13
+ - name: Checkout code
14
+ uses: actions/checkout@v4
15
+
16
+ - name: Install uv
17
+ uses: astral-sh/setup-uv@v4
18
+ with:
19
+ enable-cache: true
20
+
21
+ - name: Set up Python
22
+ uses: actions/setup-python@v5
23
+ with:
24
+ python-version: "3.13"
25
+
26
+ - name: Install dependencies
27
+ run: uv sync --all-groups
28
+
29
+ - name: Check formatting with ruff
30
+ run: uv run ruff format --check .
31
+
32
+ - name: Lint with ruff
33
+ run: uv run ruff check .
34
+
35
+ - name: Type check with ty
36
+ run: uv run ty check
37
+
38
+ test:
39
+ name: Run Tests
40
+ runs-on: ubuntu-latest
41
+ steps:
42
+ - name: Checkout code
43
+ uses: actions/checkout@v4
44
+
45
+ - name: Install uv
46
+ uses: astral-sh/setup-uv@v4
47
+ with:
48
+ enable-cache: true
49
+
50
+ - name: Set up Python
51
+ uses: actions/setup-python@v5
52
+ with:
53
+ python-version: "3.13"
54
+
55
+ - name: Install dependencies
56
+ run: uv sync --all-groups
57
+
58
+ - name: Run tests
59
+ run: uv run pytest tests/ -v
@@ -0,0 +1,97 @@
1
+ name: Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - "v*"
7
+ branches:
8
+ - main
9
+ workflow_dispatch:
10
+ inputs:
11
+ tag:
12
+ description: 'Git tag to publish (e.g., v0.1.0)'
13
+ required: true
14
+ type: string
15
+
16
+ jobs:
17
+ publish-pypi:
18
+ name: Build and Publish to Production PyPI
19
+ runs-on: ubuntu-latest
20
+ environment:
21
+ name: pypi
22
+ url: https://pypi.org/project/aws-expect/
23
+
24
+ steps:
25
+ - name: Checkout code
26
+ uses: actions/checkout@v4
27
+ with:
28
+ ref: ${{ github.event.inputs.tag || github.ref }}
29
+
30
+ - name: Validate version
31
+ run: |
32
+ VERSION=$(grep -Po 'version = "\K[^"]*' pyproject.toml)
33
+ echo "Version in pyproject.toml: $VERSION"
34
+
35
+ if [[ $VERSION =~ (dev|alpha|beta|rc) ]]; then
36
+ echo "❌ ERROR: Cannot publish pre-release version '$VERSION' to production PyPI"
37
+ echo "Please remove dev/alpha/beta/rc suffix from version in pyproject.toml"
38
+ exit 1
39
+ fi
40
+
41
+ echo "✅ Version validated: $VERSION"
42
+
43
+ - name: Install uv
44
+ uses: astral-sh/setup-uv@v4
45
+ with:
46
+ enable-cache: true
47
+
48
+ - name: Set up Python
49
+ uses: actions/setup-python@v5
50
+ with:
51
+ python-version: "3.13"
52
+
53
+ - name: Install dependencies
54
+ run: uv sync --all-groups
55
+
56
+ - name: Run quality checks
57
+ run: |
58
+ uv run ruff format --check .
59
+ uv run ruff check .
60
+ uv run ty check
61
+
62
+ - name: Run tests
63
+ run: uv run pytest tests/ -v
64
+
65
+ - name: Build package
66
+ run: uv build
67
+
68
+ - name: Publish to PyPI
69
+ env:
70
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TOKEN }}
71
+ run: |
72
+ uv publish
73
+
74
+ - name: Create GitHub Release
75
+ if: startsWith(github.ref, 'refs/tags/')
76
+ uses: softprops/action-gh-release@v1
77
+ with:
78
+ files: dist/*
79
+ generate_release_notes: true
80
+ draft: false
81
+ prerelease: false
82
+ body: |
83
+ ## Installation
84
+
85
+ ```bash
86
+ pip install aws-expect
87
+ ```
88
+
89
+ Or with uv:
90
+
91
+ ```bash
92
+ uv add aws-expect
93
+ ```
94
+
95
+ ## Documentation
96
+
97
+ See [README.md](https://github.com/PhishStick-hub/aws-expect#readme) for usage examples.
@@ -0,0 +1,55 @@
1
+ name: Publish to TestPyPI
2
+
3
+ on:
4
+ push:
5
+ branches:
6
+ - develop
7
+ workflow_dispatch:
8
+
9
+ jobs:
10
+ publish-testpypi:
11
+ name: Build and Publish to TestPyPI
12
+ runs-on: ubuntu-latest
13
+ environment:
14
+ name: testpypi
15
+ url: https://test.pypi.org/project/aws-expect/
16
+
17
+ steps:
18
+ - name: Checkout code
19
+ uses: actions/checkout@v4
20
+
21
+ - name: Install uv
22
+ uses: astral-sh/setup-uv@v4
23
+ with:
24
+ enable-cache: true
25
+
26
+ - name: Set up Python
27
+ uses: actions/setup-python@v5
28
+ with:
29
+ python-version: "3.13"
30
+
31
+ - name: Install dependencies
32
+ run: uv sync --all-groups
33
+
34
+ - name: Run quality checks
35
+ run: |
36
+ uv run ruff format --check .
37
+ uv run ruff check .
38
+ uv run ty check
39
+
40
+ - name: Run tests
41
+ run: uv run pytest tests/ -v
42
+
43
+ - name: Build package
44
+ run: uv build
45
+
46
+ - name: Publish to TestPyPI
47
+ env:
48
+ UV_PUBLISH_TOKEN: ${{ secrets.PYPI_TEST_TOKEN }}
49
+ run: |
50
+ uv publish --publish-url https://test.pypi.org/legacy/
51
+
52
+ - name: Comment on commit with TestPyPI link
53
+ run: |
54
+ VERSION=$(grep -Po 'version = "\K[^"]*' pyproject.toml)
55
+ echo "📦 Published to TestPyPI: https://test.pypi.org/project/aws-expect/$VERSION/"
@@ -0,0 +1,10 @@
1
+ # Python-generated files
2
+ __pycache__/
3
+ *.py[oc]
4
+ build/
5
+ dist/
6
+ wheels/
7
+ *.egg-info
8
+
9
+ # Virtual environments
10
+ .venv
@@ -0,0 +1 @@
1
+ 3.13
@@ -0,0 +1,206 @@
1
+ # AGENTS.md - aws-expect Coding Guidelines
2
+
3
+ This file provides guidance for AI agents working on the aws-expect repository.
4
+
5
+ ## Project Overview
6
+
7
+ A Python library providing declarative waiters for AWS services (S3, DynamoDB) using boto3.
8
+
9
+ - **Language**: Python 3.13+
10
+ - **Package Manager**: uv
11
+ - **Build System**: hatchling
12
+ - **Test Framework**: pytest with testcontainers/LocalStack
13
+
14
+ ## Build Commands
15
+
16
+ ```bash
17
+ # Install all dependencies (including dev)
18
+ uv sync --all-groups
19
+
20
+ # Run all tests (requires Docker)
21
+ uv run pytest tests/ -v
22
+
23
+ # Run a single test file
24
+ uv run pytest tests/test_s3_exist.py -v
25
+
26
+ # Run a specific test class
27
+ uv run pytest tests/test_s3_exist.py::TestToExist -v
28
+
29
+ # Run a single test method
30
+ uv run pytest tests/test_s3_exist.py::TestToExist::test_returns_metadata_when_object_exists -v
31
+
32
+ # Build package
33
+ uv build
34
+ ```
35
+
36
+ ## Code Style Guidelines
37
+
38
+ ### Imports
39
+
40
+ - Use `from __future__ import annotations` when needed for forward references
41
+ - Group imports: stdlib → third-party → local
42
+ - Use absolute imports within the package (e.g., `from aws_expect.exceptions import ...`)
43
+
44
+ ### Type Hints
45
+
46
+ - Use type hints for all function parameters and return types
47
+ - Use `Any` from `typing` for boto3 resources/clients (they're dynamically typed)
48
+ - Prefer union syntax: `dict[str, Any] | None` instead of `Optional[dict[str, Any]]`
49
+
50
+ ### Naming Conventions
51
+
52
+ - **Classes**: PascalCase (e.g., `S3ObjectExpectation`, `WaitTimeoutError`)
53
+ - **Functions/Methods**: snake_case (e.g., `to_exist`, `expect_s3`)
54
+ - **Private attributes**: prefix with underscore (e.g., `self._table`, `self._bucket`)
55
+ - **Constants**: UPPER_CASE for module-level constants
56
+ - **Exceptions**: Suffix with `Error`, inherit from base `WaitTimeoutError`
57
+
58
+ ### Docstrings
59
+
60
+ Use Google-style docstrings:
61
+
62
+ ```python
63
+ def to_exist(self, timeout: float = 30) -> dict[str, Any]:
64
+ """Wait for the object to exist.
65
+
66
+ Args:
67
+ timeout: Maximum time in seconds to wait.
68
+
69
+ Returns:
70
+ The response metadata dict.
71
+
72
+ Raises:
73
+ S3WaitTimeoutError: If the object does not exist within timeout.
74
+ """
75
+ ```
76
+
77
+ ### Error Handling
78
+
79
+ - All timeout exceptions inherit from `WaitTimeoutError` base class
80
+ - Exception constructors should store relevant context (bucket, key, timeout, etc.)
81
+ - Use `raise ... from exc` when wrapping exceptions
82
+
83
+ ### Project Structure
84
+
85
+ ```
86
+ aws_expect/
87
+ ├── __init__.py # Public API exports with __all__
88
+ ├── exceptions.py # Exception hierarchy
89
+ ├── expect.py # Public API entry points (expect_s3, expect_dynamodb)
90
+ ├── s3.py # S3ObjectExpectation implementation
91
+ └── dynamodb.py # DynamoDBItemExpectation implementation
92
+ tests/
93
+ ├── conftest.py # pytest fixtures (LocalStack, boto3 resources)
94
+ ├── test_s3_*.py # S3 tests
95
+ └── test_dynamodb_*.py # DynamoDB tests
96
+ ```
97
+
98
+ ### Key Patterns
99
+
100
+ **Creating Expectation Classes:**
101
+
102
+ - Accept boto3 resource objects in constructor
103
+ - Store as private attributes (e.g., `self._obj`, `self._table`)
104
+ - Use `to_exist()` and `to_not_exist()` method naming
105
+ - Support `timeout` and `poll_interval` parameters
106
+
107
+ **Polling Implementation:**
108
+
109
+ ```python
110
+ default_delay = max(1, math.ceil(poll_interval)) # minimum 1 second
111
+ deadline = time.monotonic() + timeout
112
+ while True:
113
+ # check condition
114
+ remaining = deadline - time.monotonic()
115
+ if remaining <= 0:
116
+ raise TimeoutError(...)
117
+ time.sleep(min(delay, remaining))
118
+ ```
119
+
120
+ ### Testing
121
+
122
+ - Tests use LocalStack containers via testcontainers
123
+ - Use pytest fixtures from `conftest.py` for AWS resources
124
+ - Tests are organized in classes (e.g., `class TestToExist:`)
125
+ - Use short timeouts in tests (2-10 seconds) for fast feedback
126
+ - Use threading.Timer for async operations in tests
127
+
128
+ ### Linting and Type Checking
129
+
130
+ This project uses `ty` for type checking and `ruff` for linting and formatting:
131
+
132
+ **Type Checking with ty:**
133
+
134
+ ```bash
135
+ # Run type checker (activated environment)
136
+ ty check
137
+
138
+ # Run type checker (without activated environment)
139
+ uv run ty check
140
+ ```
141
+
142
+ **Linting and Formatting with ruff:**
143
+
144
+ ```bash
145
+ # Check code with ruff
146
+ uv run ruff check aws_expect/ tests/
147
+
148
+ # Auto-fix issues
149
+ uv run ruff check --fix aws_expect/ tests/
150
+
151
+ # Format code
152
+ uv run ruff format aws_expect/ tests/
153
+ ```
154
+
155
+ ### Exception Handling Pattern
156
+
157
+ When creating new service waiters, follow this exception pattern:
158
+
159
+ ```python
160
+ class ServiceWaitTimeoutError(WaitTimeoutError):
161
+ """Raised when a service wait operation exceeds the specified timeout."""
162
+
163
+ def __init__(
164
+ self,
165
+ resource_id: str,
166
+ timeout: float,
167
+ message: str | None = None,
168
+ ) -> None:
169
+ self.resource_id = resource_id
170
+ self.timeout = timeout
171
+ if message is not None:
172
+ msg = message
173
+ else:
174
+ msg = f"Timed out after {timeout}s waiting for {resource_id}"
175
+ super().__init__(msg)
176
+ ```
177
+
178
+ ### Testing Best Practices
179
+
180
+ - **Use descriptive test class names**: `TestS3ToExist`, `TestDynamoDBItemOperations`
181
+ - **Test both success and failure cases**: Always include timeout/exception tests
182
+ - **Use fixtures for resource setup**: Leverage `conftest.py` fixtures
183
+ - **Mock time-sensitive operations**: Use `threading.Timer` to simulate delayed operations
184
+ - **Test async behavior**: Verify waiters work when resources appear mid-poll
185
+ - **Short test timeouts**: Use 2-10 second timeouts in tests for fast feedback
186
+
187
+ ### MCP Tools
188
+
189
+ Always use Context7 MCP when you need library/API documentation, code generation, code quality verification, setup or configuration steps without the user having to explicitly ask.
190
+
191
+ ### Quality Checks
192
+
193
+ **IMPORTANT**: After making any changes to the project, you MUST run the following checks in order:
194
+
195
+ 1. **Run local tests**: `uv run pytest tests/ -v` - Ensure all tests pass
196
+ 2. **Run type checker**: `uv run ty check` (or `ty check` if ty is globally available) - Verify type correctness
197
+ 3. **Run linter**: `uv run ruff check .` - Check for code issues
198
+ 4. **Run formatter**: `uv run ruff format .` - Ensure consistent formatting
199
+
200
+ **If any of these checks fail, you MUST fix the issues before considering the task complete.**
201
+
202
+ Additional pre-commit checks:
203
+
204
+ - Verify docstrings are complete for all public APIs
205
+ - Ensure `__all__` is updated in `__init__.py` for new exports
206
+ - Use Context7 MCP for library/API documentation and code quality verification when needed