ai-lls-lib 1.0.0__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,220 @@
1
+ Metadata-Version: 2.3
2
+ Name: ai-lls-lib
3
+ Version: 1.0.0
4
+ Summary: Landline Scrubber core library - phone verification and DNC checking
5
+ Author: LandlineScrubber Team
6
+ Requires-Python: >=3.12,<4.0
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Programming Language :: Python :: 3.12
9
+ Classifier: Programming Language :: Python :: 3.13
10
+ Requires-Dist: aws-lambda-powertools (>=2.30.0,<3.0.0)
11
+ Requires-Dist: boto3 (>=1.34.0,<2.0.0)
12
+ Requires-Dist: click (>=8.1.0,<9.0.0)
13
+ Requires-Dist: httpx (>=0.25.0,<0.26.0)
14
+ Requires-Dist: phonenumbers (>=8.13.0,<9.0.0)
15
+ Requires-Dist: pydantic (>=2.5.0,<3.0.0)
16
+ Requires-Dist: rich (>=14.0,<15.0)
17
+ Description-Content-Type: text/markdown
18
+
19
+ # AI LLS Library
20
+
21
+ Core business logic library and CLI tools for Landline Scrubber - phone verification and DNC checking.
22
+
23
+ ## Features
24
+
25
+ - Phone number normalization (E.164 format)
26
+ - Line type detection (mobile/landline/voip)
27
+ - DNC (Do Not Call) list checking
28
+ - DynamoDB caching with 30-day TTL
29
+ - Bulk CSV processing
30
+ - Infrastructure-aware CLI for admin operations
31
+ - AWS Lambda PowerTools integration
32
+
33
+ ## Installation
34
+
35
+ ```bash
36
+ # Install library with Poetry
37
+ poetry install
38
+
39
+ # Install CLI globally
40
+ pip install -e .
41
+ ```
42
+
43
+ ## Library Usage
44
+
45
+ ### Single Phone Verification
46
+
47
+ ```python
48
+ from ai_lls_lib import PhoneVerifier, DynamoDBCache
49
+
50
+ cache = DynamoDBCache(table_name="phone-cache")
51
+ verifier = PhoneVerifier(cache)
52
+
53
+ result = verifier.verify_sync("+15551234567")
54
+ print(f"Line type: {result.line_type}")
55
+ print(f"DNC: {result.dnc}")
56
+ print(f"From cache: {result.cached}")
57
+ ```
58
+
59
+ ### Bulk Processing
60
+
61
+ ```python
62
+ from ai_lls_lib import BulkProcessor, PhoneVerifier, DynamoDBCache
63
+
64
+ cache = DynamoDBCache(table_name="phone-cache")
65
+ verifier = PhoneVerifier(cache)
66
+ processor = BulkProcessor(verifier)
67
+
68
+ results = processor.process_csv_sync("/path/to/phones.csv")
69
+ processor.generate_results_csv(
70
+ original_path="/path/to/phones.csv",
71
+ results=results,
72
+ output_path="/path/to/results.csv"
73
+ )
74
+ ```
75
+
76
+ ## CLI Usage
77
+
78
+ The `ai-lls` CLI provides infrastructure-aware administrative tools:
79
+
80
+ ### Verification Commands
81
+ ```bash
82
+ # Verify single phone
83
+ ai-lls verify phone +15551234567 --stack landline-api
84
+
85
+ # Bulk verify CSV
86
+ ai-lls verify bulk input.csv -o output.csv --stack landline-api
87
+ ```
88
+
89
+ ### Cache Management
90
+ ```bash
91
+ # Show cache statistics
92
+ ai-lls cache stats --stack landline-api
93
+
94
+ # Get cached entry
95
+ ai-lls cache get +15551234567 --stack landline-api
96
+
97
+ # Invalidate cache entry
98
+ ai-lls cache invalidate +15551234567 --stack landline-api
99
+
100
+ # Clear old entries
101
+ ai-lls cache clear --older-than 20 --stack landline-api
102
+ ```
103
+
104
+ ### Administrative Commands
105
+ ```bash
106
+ # Manage user credits
107
+ ai-lls admin user-credits user123 --add 100
108
+ ai-lls admin user-credits user123 --set 500
109
+
110
+ # List API keys
111
+ ai-lls admin api-keys --user user123
112
+
113
+ # Check queue status
114
+ ai-lls admin queue-stats
115
+
116
+ # View secrets (masked)
117
+ ai-lls admin secrets --stack landline-api
118
+ ```
119
+
120
+ ### Test Stack Management
121
+ ```bash
122
+ # Deploy test stack
123
+ ai-lls test-stack deploy
124
+
125
+ # Check status
126
+ ai-lls test-stack status
127
+
128
+ # Run integration tests
129
+ ai-lls test-stack test
130
+
131
+ # Delete test stack
132
+ ai-lls test-stack delete
133
+ ```
134
+
135
+ ## Project Structure
136
+
137
+ ```
138
+ ai-lls-lib/
139
+ ├── src/ai_lls_lib/
140
+ │ ├── core/ # Business logic (infrastructure-agnostic)
141
+ │ │ ├── models.py # Pydantic models
142
+ │ │ ├── verifier.py # Phone verification
143
+ │ │ ├── processor.py # Bulk processing
144
+ │ │ └── cache.py # DynamoDB cache
145
+ │ ├── cli/ # Infrastructure-aware CLI
146
+ │ │ ├── __main__.py # Entry point
147
+ │ │ ├── commands/ # Command modules
148
+ │ │ └── aws_client.py # AWS operations
149
+ │ └── testing/ # Test utilities
150
+ │ └── fixtures.py # Test data
151
+ ├── tests/
152
+ │ ├── unit/ # Mocked tests
153
+ │ └── integration/ # AWS integration tests
154
+ └── test-stack.yaml # Test infrastructure
155
+ ```
156
+
157
+ ## Testing
158
+
159
+ ```bash
160
+ # Run unit tests (mocked AWS)
161
+ poetry run pytest tests/unit -v
162
+
163
+ # Deploy test stack for integration tests
164
+ ai-lls test-stack deploy
165
+
166
+ # Run integration tests (requires test stack)
167
+ TEST_STACK_NAME=ai-lls-lib-test poetry run pytest tests/integration -v
168
+
169
+ # All tests with coverage
170
+ poetry run pytest --cov=src --cov-report=html
171
+
172
+ # Clean up
173
+ ai-lls test-stack delete
174
+ ```
175
+
176
+ ## Development
177
+
178
+ ### Current Stub Implementation
179
+
180
+ For demo purposes, verification uses stub logic based on last digit:
181
+ - Ends in 3: mobile, not on DNC
182
+ - Ends in 2: landline, not on DNC
183
+ - Ends in 1: mobile, on DNC
184
+ - Ends in 0: landline, on DNC
185
+ - Otherwise: mobile, not on DNC
186
+
187
+ TODO markers indicate where real API integration will be added.
188
+
189
+ ### Code Quality
190
+
191
+ ```bash
192
+ # Format code
193
+ poetry run black src/ tests/
194
+ poetry run isort src/ tests/
195
+
196
+ # Type checking
197
+ poetry run mypy src/
198
+
199
+ # Run pre-commit hooks
200
+ pre-commit run --all-files
201
+ ```
202
+
203
+ ## Environment Variables
204
+
205
+ - `DNC_API_KEY` - DNC verification API key
206
+ - `DNC_CHECK_API_KEY` - Alternative DNC service
207
+ - `PHONE_VERIFY_API_KEY` - Line type verification
208
+ - `AWS_REGION` - AWS region (default: us-east-1)
209
+ - `AWS_PROFILE` - AWS profile for CLI operations
210
+
211
+ ## License
212
+
213
+ Proprietary - All rights reserved
214
+
215
+ ## Release Process
216
+
217
+ This library uses semantic versioning and publishes to:
218
+ - TestPyPI on dev branch pushes (pre-release versions)
219
+ - PyPI on main branch pushes (stable releases)
220
+
@@ -0,0 +1,201 @@
1
+ # AI LLS Library
2
+
3
+ Core business logic library and CLI tools for Landline Scrubber - phone verification and DNC checking.
4
+
5
+ ## Features
6
+
7
+ - Phone number normalization (E.164 format)
8
+ - Line type detection (mobile/landline/voip)
9
+ - DNC (Do Not Call) list checking
10
+ - DynamoDB caching with 30-day TTL
11
+ - Bulk CSV processing
12
+ - Infrastructure-aware CLI for admin operations
13
+ - AWS Lambda PowerTools integration
14
+
15
+ ## Installation
16
+
17
+ ```bash
18
+ # Install library with Poetry
19
+ poetry install
20
+
21
+ # Install CLI globally
22
+ pip install -e .
23
+ ```
24
+
25
+ ## Library Usage
26
+
27
+ ### Single Phone Verification
28
+
29
+ ```python
30
+ from ai_lls_lib import PhoneVerifier, DynamoDBCache
31
+
32
+ cache = DynamoDBCache(table_name="phone-cache")
33
+ verifier = PhoneVerifier(cache)
34
+
35
+ result = verifier.verify_sync("+15551234567")
36
+ print(f"Line type: {result.line_type}")
37
+ print(f"DNC: {result.dnc}")
38
+ print(f"From cache: {result.cached}")
39
+ ```
40
+
41
+ ### Bulk Processing
42
+
43
+ ```python
44
+ from ai_lls_lib import BulkProcessor, PhoneVerifier, DynamoDBCache
45
+
46
+ cache = DynamoDBCache(table_name="phone-cache")
47
+ verifier = PhoneVerifier(cache)
48
+ processor = BulkProcessor(verifier)
49
+
50
+ results = processor.process_csv_sync("/path/to/phones.csv")
51
+ processor.generate_results_csv(
52
+ original_path="/path/to/phones.csv",
53
+ results=results,
54
+ output_path="/path/to/results.csv"
55
+ )
56
+ ```
57
+
58
+ ## CLI Usage
59
+
60
+ The `ai-lls` CLI provides infrastructure-aware administrative tools:
61
+
62
+ ### Verification Commands
63
+ ```bash
64
+ # Verify single phone
65
+ ai-lls verify phone +15551234567 --stack landline-api
66
+
67
+ # Bulk verify CSV
68
+ ai-lls verify bulk input.csv -o output.csv --stack landline-api
69
+ ```
70
+
71
+ ### Cache Management
72
+ ```bash
73
+ # Show cache statistics
74
+ ai-lls cache stats --stack landline-api
75
+
76
+ # Get cached entry
77
+ ai-lls cache get +15551234567 --stack landline-api
78
+
79
+ # Invalidate cache entry
80
+ ai-lls cache invalidate +15551234567 --stack landline-api
81
+
82
+ # Clear old entries
83
+ ai-lls cache clear --older-than 20 --stack landline-api
84
+ ```
85
+
86
+ ### Administrative Commands
87
+ ```bash
88
+ # Manage user credits
89
+ ai-lls admin user-credits user123 --add 100
90
+ ai-lls admin user-credits user123 --set 500
91
+
92
+ # List API keys
93
+ ai-lls admin api-keys --user user123
94
+
95
+ # Check queue status
96
+ ai-lls admin queue-stats
97
+
98
+ # View secrets (masked)
99
+ ai-lls admin secrets --stack landline-api
100
+ ```
101
+
102
+ ### Test Stack Management
103
+ ```bash
104
+ # Deploy test stack
105
+ ai-lls test-stack deploy
106
+
107
+ # Check status
108
+ ai-lls test-stack status
109
+
110
+ # Run integration tests
111
+ ai-lls test-stack test
112
+
113
+ # Delete test stack
114
+ ai-lls test-stack delete
115
+ ```
116
+
117
+ ## Project Structure
118
+
119
+ ```
120
+ ai-lls-lib/
121
+ ├── src/ai_lls_lib/
122
+ │ ├── core/ # Business logic (infrastructure-agnostic)
123
+ │ │ ├── models.py # Pydantic models
124
+ │ │ ├── verifier.py # Phone verification
125
+ │ │ ├── processor.py # Bulk processing
126
+ │ │ └── cache.py # DynamoDB cache
127
+ │ ├── cli/ # Infrastructure-aware CLI
128
+ │ │ ├── __main__.py # Entry point
129
+ │ │ ├── commands/ # Command modules
130
+ │ │ └── aws_client.py # AWS operations
131
+ │ └── testing/ # Test utilities
132
+ │ └── fixtures.py # Test data
133
+ ├── tests/
134
+ │ ├── unit/ # Mocked tests
135
+ │ └── integration/ # AWS integration tests
136
+ └── test-stack.yaml # Test infrastructure
137
+ ```
138
+
139
+ ## Testing
140
+
141
+ ```bash
142
+ # Run unit tests (mocked AWS)
143
+ poetry run pytest tests/unit -v
144
+
145
+ # Deploy test stack for integration tests
146
+ ai-lls test-stack deploy
147
+
148
+ # Run integration tests (requires test stack)
149
+ TEST_STACK_NAME=ai-lls-lib-test poetry run pytest tests/integration -v
150
+
151
+ # All tests with coverage
152
+ poetry run pytest --cov=src --cov-report=html
153
+
154
+ # Clean up
155
+ ai-lls test-stack delete
156
+ ```
157
+
158
+ ## Development
159
+
160
+ ### Current Stub Implementation
161
+
162
+ For demo purposes, verification uses stub logic based on last digit:
163
+ - Ends in 3: mobile, not on DNC
164
+ - Ends in 2: landline, not on DNC
165
+ - Ends in 1: mobile, on DNC
166
+ - Ends in 0: landline, on DNC
167
+ - Otherwise: mobile, not on DNC
168
+
169
+ TODO markers indicate where real API integration will be added.
170
+
171
+ ### Code Quality
172
+
173
+ ```bash
174
+ # Format code
175
+ poetry run black src/ tests/
176
+ poetry run isort src/ tests/
177
+
178
+ # Type checking
179
+ poetry run mypy src/
180
+
181
+ # Run pre-commit hooks
182
+ pre-commit run --all-files
183
+ ```
184
+
185
+ ## Environment Variables
186
+
187
+ - `DNC_API_KEY` - DNC verification API key
188
+ - `DNC_CHECK_API_KEY` - Alternative DNC service
189
+ - `PHONE_VERIFY_API_KEY` - Line type verification
190
+ - `AWS_REGION` - AWS region (default: us-east-1)
191
+ - `AWS_PROFILE` - AWS profile for CLI operations
192
+
193
+ ## License
194
+
195
+ Proprietary - All rights reserved
196
+
197
+ ## Release Process
198
+
199
+ This library uses semantic versioning and publishes to:
200
+ - TestPyPI on dev branch pushes (pre-release versions)
201
+ - PyPI on main branch pushes (stable releases)
@@ -0,0 +1,106 @@
1
+ [tool.poetry]
2
+ name = "ai-lls-lib"
3
+ version = "1.0.0"
4
+ description = "Landline Scrubber core library - phone verification and DNC checking"
5
+ authors = ["LandlineScrubber Team"]
6
+ readme = "README.md"
7
+ packages = [{include = "ai_lls_lib", from = "src"}]
8
+
9
+ [tool.poetry.dependencies]
10
+ python = "^3.12"
11
+ boto3 = "^1.34.0"
12
+ pydantic = "^2.5.0"
13
+ phonenumbers = "^8.13.0"
14
+ httpx = "^0.25.0"
15
+ aws-lambda-powertools = "^2.30.0"
16
+ click = "^8.1.0"
17
+ rich = "^14.0"
18
+
19
+ [tool.poetry.group.dev.dependencies]
20
+ pytest = "^7.4.0"
21
+ pytest-cov = "^4.1.0"
22
+ pytest-asyncio = "^0.21.0"
23
+ black = "^23.12.0"
24
+ isort = "^5.13.0"
25
+ mypy = "^1.8.0"
26
+ boto3-stubs = {extras = ["dynamodb", "s3", "sqs"], version = "^1.34.0"}
27
+ moto = {extras = ["dynamodb", "s3", "sqs"], version = "^4.2.0"}
28
+ python-semantic-release = "^10.3.1"
29
+
30
+ [build-system]
31
+ requires = ["poetry-core"]
32
+ build-backend = "poetry.core.masonry.api"
33
+
34
+ [tool.black]
35
+ line-length = 100
36
+ target-version = ['py312']
37
+
38
+ [tool.isort]
39
+ profile = "black"
40
+ line_length = 100
41
+
42
+ [tool.mypy]
43
+ python_version = "3.12"
44
+ warn_return_any = true
45
+ warn_unused_configs = true
46
+ disallow_untyped_defs = true
47
+
48
+ [tool.pytest.ini_options]
49
+ testpaths = ["tests"]
50
+ python_files = ["test_*.py"]
51
+ addopts = "-ra -q --strict-markers"
52
+
53
+ [tool.coverage.run]
54
+ source = ["src"]
55
+ omit = ["*/tests/*", "*/test_*.py"]
56
+
57
+ [tool.poetry.scripts]
58
+ ai-lls = "ai_lls_lib.cli.__main__:main"
59
+
60
+ [tool.semantic_release]
61
+ assets = []
62
+ commit_message = "chore(release): ai-lls-lib {version}\n\nAutomatically generated by python-semantic-release [skip ci]"
63
+ commit_parser = "angular"
64
+ logging_use_named_masks = false
65
+ major_on_zero = false
66
+ allow_zero_version = false
67
+ no_git_verify = false
68
+ tag_format = "ai-lls-lib-v{version}"
69
+ version_toml = ["pyproject.toml:tool.poetry.version"]
70
+ version_variables = ["src/ai_lls_lib/__init__.py:__version__"]
71
+ build_command = "poetry build"
72
+
73
+ [tool.semantic_release.branches.main]
74
+ match = "main"
75
+ prerelease = false
76
+
77
+ [tool.semantic_release.branches.dev]
78
+ match = "dev"
79
+ prerelease = true
80
+ prerelease_token = "rc"
81
+ version_format = "v{major}.{minor}.{patch}-{prerelease}.{prerelease_revision}"
82
+
83
+ [tool.semantic_release.changelog]
84
+ mode = "update"
85
+ changelog_file = "CHANGELOG.md"
86
+ exclude_commit_patterns = [
87
+ '''chore(?:\([^)]*?\))?: .+''',
88
+ '''ci(?:\([^)]*?\))?: .+''',
89
+ '''refactor(?:\([^)]*?\))?: .+''',
90
+ '''style(?:\([^)]*?\))?: .+''',
91
+ '''test(?:\([^)]*?\))?: .+''',
92
+ '''build\((?!deps\): .+)''',
93
+ ]
94
+
95
+ [tool.semantic_release.remote]
96
+ name = "origin"
97
+ type = "github"
98
+ ignore_token_for_push = false
99
+ insecure = false
100
+
101
+ [tool.semantic_release.remote.token]
102
+ env = "GH_TOKEN"
103
+
104
+ [tool.semantic_release.publish]
105
+ dist_glob_patterns = ["libs/python/ai-lls-lib/dist/*"]
106
+ upload_to_vcs_release = false
@@ -0,0 +1,27 @@
1
+ """
2
+ AI LLS Library - Core business logic for Landline Scrubber
3
+ """
4
+ from ai_lls_lib.core.models import (
5
+ PhoneVerification,
6
+ BulkJob,
7
+ BulkJobStatus,
8
+ LineType,
9
+ VerificationSource,
10
+ JobStatus
11
+ )
12
+ from ai_lls_lib.core.verifier import PhoneVerifier
13
+ from ai_lls_lib.core.processor import BulkProcessor
14
+ from ai_lls_lib.core.cache import DynamoDBCache
15
+
16
+ __version__ = "1.0.0"
17
+ __all__ = [
18
+ "PhoneVerification",
19
+ "BulkJob",
20
+ "BulkJobStatus",
21
+ "LineType",
22
+ "VerificationSource",
23
+ "JobStatus",
24
+ "PhoneVerifier",
25
+ "BulkProcessor",
26
+ "DynamoDBCache",
27
+ ]
@@ -0,0 +1,3 @@
1
+ """
2
+ Landline Scrubber CLI - Infrastructure-aware administrative tools
3
+ """
@@ -0,0 +1,29 @@
1
+ """
2
+ Landline Scrubber CLI entry point
3
+ """
4
+ import click
5
+ import sys
6
+ from ai_lls_lib.cli.commands import verify, cache, admin, test_stack
7
+
8
+ @click.group()
9
+ @click.version_option(version="0.1.0", prog_name="ai-lls")
10
+ def cli():
11
+ """Landline Scrubber CLI - Administrative and debugging tools"""
12
+ pass
13
+
14
+ # Register command groups
15
+ cli.add_command(verify.verify_group)
16
+ cli.add_command(cache.cache_group)
17
+ cli.add_command(admin.admin_group)
18
+ cli.add_command(test_stack.test_stack_group)
19
+
20
+ def main():
21
+ """Main entry point"""
22
+ try:
23
+ cli()
24
+ except Exception as e:
25
+ click.echo(f"Error: {e}", err=True)
26
+ sys.exit(1)
27
+
28
+ if __name__ == "__main__":
29
+ main()
@@ -0,0 +1,115 @@
1
+ """
2
+ AWS client utilities for CLI operations
3
+ """
4
+ import os
5
+ import boto3
6
+ from typing import Optional, Any, Dict
7
+ from botocore.exceptions import ClientError
8
+ import click
9
+
10
+ class AWSClient:
11
+ """Wrapper for AWS operations with proper error handling"""
12
+
13
+ def __init__(self, region: Optional[str] = None, profile: Optional[str] = None):
14
+ """Initialize AWS clients"""
15
+ self.region = region or os.environ.get("AWS_REGION", "us-east-1")
16
+ self.profile = profile
17
+
18
+ # Create session
19
+ if profile:
20
+ self.session = boto3.Session(profile_name=profile, region_name=self.region)
21
+ else:
22
+ self.session = boto3.Session(region_name=self.region)
23
+
24
+ # Lazy-load clients
25
+ self._dynamodb = None
26
+ self._s3 = None
27
+ self._sqs = None
28
+ self._secretsmanager = None
29
+ self._cloudformation = None
30
+
31
+ @property
32
+ def dynamodb(self):
33
+ """Get DynamoDB client"""
34
+ if not self._dynamodb:
35
+ self._dynamodb = self.session.resource('dynamodb')
36
+ return self._dynamodb
37
+
38
+ @property
39
+ def s3(self):
40
+ """Get S3 client"""
41
+ if not self._s3:
42
+ self._s3 = self.session.client('s3')
43
+ return self._s3
44
+
45
+ @property
46
+ def sqs(self):
47
+ """Get SQS client"""
48
+ if not self._sqs:
49
+ self._sqs = self.session.client('sqs')
50
+ return self._sqs
51
+
52
+ @property
53
+ def secretsmanager(self):
54
+ """Get Secrets Manager client"""
55
+ if not self._secretsmanager:
56
+ self._secretsmanager = self.session.client('secretsmanager')
57
+ return self._secretsmanager
58
+
59
+ @property
60
+ def cloudformation(self):
61
+ """Get CloudFormation client"""
62
+ if not self._cloudformation:
63
+ self._cloudformation = self.session.client('cloudformation')
64
+ return self._cloudformation
65
+
66
+ def get_stack_outputs(self, stack_name: str) -> Dict[str, str]:
67
+ """Get CloudFormation stack outputs"""
68
+ try:
69
+ response = self.cloudformation.describe_stacks(StackName=stack_name)
70
+ stack = response['Stacks'][0]
71
+ outputs = {}
72
+ for output in stack.get('Outputs', []):
73
+ outputs[output['OutputKey']] = output['OutputValue']
74
+ return outputs
75
+ except ClientError as e:
76
+ if e.response['Error']['Code'] == 'ValidationError':
77
+ raise click.ClickException(f"Stack '{stack_name}' not found")
78
+ raise
79
+
80
+ def get_table_name(self, stack_name: str, logical_name: str) -> str:
81
+ """Get actual table name from stack"""
82
+ try:
83
+ response = self.cloudformation.describe_stack_resource(
84
+ StackName=stack_name,
85
+ LogicalResourceId=logical_name
86
+ )
87
+ return response['StackResourceDetail']['PhysicalResourceId']
88
+ except ClientError:
89
+ # Fallback to conventional naming
90
+ return f"{stack_name}-{logical_name.lower()}"
91
+
92
+ def scan_table(self, table_name: str, limit: int = 100) -> list:
93
+ """Scan DynamoDB table"""
94
+ try:
95
+ table = self.dynamodb.Table(table_name)
96
+ response = table.scan(Limit=limit)
97
+ return response.get('Items', [])
98
+ except ClientError as e:
99
+ raise click.ClickException(f"Error scanning table: {e}")
100
+
101
+ def put_item(self, table_name: str, item: dict) -> None:
102
+ """Put item to DynamoDB"""
103
+ try:
104
+ table = self.dynamodb.Table(table_name)
105
+ table.put_item(Item=item)
106
+ except ClientError as e:
107
+ raise click.ClickException(f"Error putting item: {e}")
108
+
109
+ def delete_item(self, table_name: str, key: dict) -> None:
110
+ """Delete item from DynamoDB"""
111
+ try:
112
+ table = self.dynamodb.Table(table_name)
113
+ table.delete_item(Key=key)
114
+ except ClientError as e:
115
+ raise click.ClickException(f"Error deleting item: {e}")
@@ -0,0 +1,3 @@
1
+ """
2
+ CLI command modules
3
+ """