nui-lambda-shared-utils 1.0.0__tar.gz → 1.0.2__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.
Files changed (57) hide show
  1. nui_lambda_shared_utils-1.0.2/.github/workflows/ci.yml +108 -0
  2. nui_lambda_shared_utils-1.0.2/.github/workflows/publish.yml +136 -0
  3. nui_lambda_shared_utils-1.0.2/.github/workflows/test.yml +44 -0
  4. nui_lambda_shared_utils-1.0.2/CLAUDE.md +218 -0
  5. nui_lambda_shared_utils-1.0.2/CONTRIBUTING.md +281 -0
  6. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/PKG-INFO +33 -1
  7. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/README.md +32 -0
  8. nui_lambda_shared_utils-1.0.2/docs/slack_config.yaml.template +22 -0
  9. nui_lambda_shared_utils-1.0.2/mypy.ini +23 -0
  10. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/__init__.py +41 -16
  11. nui_lambda_shared_utils-1.0.2/nui_lambda_shared_utils/base_client.py +254 -0
  12. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/config.py +29 -20
  13. nui_lambda_shared_utils-1.0.2/nui_lambda_shared_utils/db_client.py +710 -0
  14. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/error_handler.py +3 -3
  15. nui_lambda_shared_utils-1.0.2/nui_lambda_shared_utils/es_client.py +360 -0
  16. nui_lambda_shared_utils-1.0.2/nui_lambda_shared_utils/slack_client.py +611 -0
  17. nui_lambda_shared_utils-1.0.2/nui_lambda_shared_utils/utils.py +291 -0
  18. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils.egg-info/SOURCES.txt +16 -1
  19. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/pyproject.toml +13 -3
  20. nui_lambda_shared_utils-1.0.2/pytest.ini +16 -0
  21. nui_lambda_shared_utils-1.0.2/requirements-test.txt +25 -0
  22. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/setup.py +2 -1
  23. nui_lambda_shared_utils-1.0.2/tests/test_aws_utils.py +327 -0
  24. nui_lambda_shared_utils-1.0.2/tests/test_base_client.py +811 -0
  25. nui_lambda_shared_utils-1.0.2/tests/test_config.py +276 -0
  26. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_db_client.py +12 -12
  27. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_es_client.py +28 -19
  28. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_secrets_helper.py +1 -1
  29. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_slack_client.py +310 -83
  30. nui_lambda_shared_utils-1.0.2/tests/test_utils.py +541 -0
  31. nui_lambda_shared_utils-1.0.0/nui_lambda_shared_utils/db_client.py +0 -521
  32. nui_lambda_shared_utils-1.0.0/nui_lambda_shared_utils/es_client.py +0 -153
  33. nui_lambda_shared_utils-1.0.0/nui_lambda_shared_utils/slack_client.py +0 -413
  34. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/LICENSE +0 -0
  35. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/MANIFEST.in +0 -0
  36. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/docs/README.md +0 -0
  37. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/docs/configuration.md +0 -0
  38. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/docs/index.md +0 -0
  39. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/docs/installation.md +0 -0
  40. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/docs/quickstart.md +0 -0
  41. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/cloudwatch_metrics.py +0 -0
  42. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/es_query_builder.py +0 -0
  43. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/secrets_helper.py +0 -0
  44. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/slack_formatter.py +0 -0
  45. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/slack_setup/__init__.py +0 -0
  46. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/slack_setup/channel_creator.py +0 -0
  47. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/slack_setup/channel_definitions.py +0 -0
  48. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/slack_setup/setup_helpers.py +0 -0
  49. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/slack_setup_cli.py +0 -0
  50. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/nui_lambda_shared_utils/timezone.py +0 -0
  51. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/setup.cfg +0 -0
  52. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/__init__.py +0 -0
  53. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_cloudwatch_metrics.py +0 -0
  54. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_error_handler.py +0 -0
  55. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_es_query_builder.py +0 -0
  56. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_slack_formatter.py +0 -0
  57. {nui_lambda_shared_utils-1.0.0 → nui_lambda_shared_utils-1.0.2}/tests/test_timezone.py +0 -0
@@ -0,0 +1,108 @@
1
+ name: CI
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master, develop ]
6
+ pull_request:
7
+ branches: [ main, master, develop ]
8
+
9
+ jobs:
10
+ test:
11
+ name: Test Python ${{ matrix.python-version }}
12
+ runs-on: ubuntu-latest
13
+ strategy:
14
+ matrix:
15
+ python-version: ['3.9', '3.10', '3.11', '3.12']
16
+
17
+ steps:
18
+ - uses: actions/checkout@v4
19
+
20
+ - name: Set up Python ${{ matrix.python-version }}
21
+ uses: actions/setup-python@v4
22
+ with:
23
+ python-version: ${{ matrix.python-version }}
24
+
25
+ - name: Cache pip dependencies
26
+ uses: actions/cache@v3
27
+ with:
28
+ path: ~/.cache/pip
29
+ key: ${{ runner.os }}-pip-${{ hashFiles('**/pyproject.toml', '**/setup.py') }}
30
+ restore-keys: |
31
+ ${{ runner.os }}-pip-
32
+
33
+ - name: Install dependencies
34
+ run: |
35
+ python -m pip install --upgrade pip
36
+ echo "Installing test requirements..."
37
+ pip install -r requirements-test.txt
38
+ echo "Installing package..."
39
+ pip install -e .
40
+ echo "Verifying key dependencies:"
41
+ python -c "import elasticsearch; print('✓ elasticsearch')" || echo "✗ elasticsearch missing"
42
+ python -c "import slack_sdk; print('✓ slack_sdk')" || echo "✗ slack_sdk missing"
43
+ python -c "import pymysql; print('✓ pymysql')" || echo "✗ pymysql missing"
44
+
45
+ - name: Auto-format with black
46
+ run: |
47
+ black nui_lambda_shared_utils tests
48
+ if ! git diff --quiet; then
49
+ echo "::warning::Code was auto-formatted by Black"
50
+ git config --local user.email "action@github.com"
51
+ git config --local user.name "GitHub Action"
52
+ git add -A
53
+ git commit -m "Auto-format code with Black [skip ci]" || echo "No changes to commit"
54
+ else
55
+ echo "✅ Code is already properly formatted"
56
+ fi
57
+
58
+ - name: Type check with mypy
59
+ run: |
60
+ mypy nui_lambda_shared_utils --ignore-missing-imports
61
+ continue-on-error: true # Don't fail CI on type errors yet
62
+
63
+ - name: Test with pytest
64
+ run: |
65
+ pytest --cov=nui_lambda_shared_utils --cov-report=xml --cov-report=term-missing -v
66
+
67
+ - name: Upload coverage to Codecov
68
+ uses: codecov/codecov-action@v3
69
+ with:
70
+ file: ./coverage.xml
71
+ flags: unittests
72
+ name: codecov-umbrella
73
+ fail_ci_if_error: false
74
+
75
+ build:
76
+ name: Build Package
77
+ runs-on: ubuntu-latest
78
+ needs: test
79
+
80
+ steps:
81
+ - uses: actions/checkout@v4
82
+
83
+ - name: Set up Python
84
+ uses: actions/setup-python@v4
85
+ with:
86
+ python-version: '3.11'
87
+
88
+ - name: Install build dependencies
89
+ run: |
90
+ python -m pip install --upgrade pip
91
+ pip install build twine
92
+
93
+ - name: Build package
94
+ run: python -m build
95
+
96
+ - name: Check package integrity
97
+ run: |
98
+ twine check dist/*
99
+ echo "Package contents:"
100
+ python -m tarfile -l dist/*.tar.gz | head -20
101
+ echo "Wheel contents:"
102
+ python -m zipfile -l dist/*.whl | head -20
103
+
104
+ - name: Test installation
105
+ run: |
106
+ pip install dist/*.whl
107
+ python -c "import nui_lambda_shared_utils; print('✅ Package imports successfully')"
108
+ python -c "from nui_lambda_shared_utils import Config, get_secret; print('✅ Core imports work')"
@@ -0,0 +1,136 @@
1
+ name: Build and Publish to PyPI
2
+
3
+ on:
4
+ push:
5
+ tags:
6
+ - 'v*' # Trigger on version tags like v1.0.0
7
+ release:
8
+ types: [published]
9
+ workflow_dispatch: # Allow manual triggering
10
+
11
+ jobs:
12
+ test:
13
+ name: Run Tests
14
+ runs-on: ubuntu-latest
15
+ strategy:
16
+ matrix:
17
+ python-version: ['3.9', '3.10', '3.11', '3.12']
18
+
19
+ steps:
20
+ - uses: actions/checkout@v4
21
+
22
+ - name: Set up Python ${{ matrix.python-version }}
23
+ uses: actions/setup-python@v4
24
+ with:
25
+ python-version: ${{ matrix.python-version }}
26
+
27
+ - name: Install dependencies
28
+ run: |
29
+ python -m pip install --upgrade pip
30
+ echo "Installing test requirements..."
31
+ pip install -r requirements-test.txt
32
+ echo "Installing package..."
33
+ pip install -e .
34
+ echo "Verifying key dependencies:"
35
+ python -c "import elasticsearch; print('✓ elasticsearch')" || echo "✗ elasticsearch missing"
36
+ python -c "import slack_sdk; print('✓ slack_sdk')" || echo "✗ slack_sdk missing"
37
+ python -c "import pymysql; print('✓ pymysql')" || echo "✗ pymysql missing"
38
+
39
+ - name: Run tests
40
+ run: |
41
+ pytest --cov=nui_lambda_shared_utils --cov-report=xml --cov-report=term-missing
42
+
43
+ - name: Upload coverage to Codecov
44
+ uses: codecov/codecov-action@v3
45
+ with:
46
+ file: ./coverage.xml
47
+ fail_ci_if_error: false
48
+
49
+ build:
50
+ name: Build Distribution
51
+ runs-on: ubuntu-latest
52
+ needs: test
53
+
54
+ steps:
55
+ - uses: actions/checkout@v4
56
+ with:
57
+ fetch-depth: 0 # Full history for version calculation
58
+
59
+ - name: Set up Python
60
+ uses: actions/setup-python@v4
61
+ with:
62
+ python-version: '3.11'
63
+
64
+ - name: Install build dependencies
65
+ run: |
66
+ python -m pip install --upgrade pip
67
+ pip install build twine
68
+
69
+ - name: Build package
70
+ run: python -m build
71
+
72
+ - name: Check package
73
+ run: |
74
+ twine check dist/*
75
+ python -m tarfile -l dist/*.tar.gz
76
+
77
+ - name: Upload artifacts
78
+ uses: actions/upload-artifact@v4
79
+ with:
80
+ name: dist
81
+ path: dist/
82
+
83
+ publish:
84
+ name: Publish to PyPI
85
+ runs-on: ubuntu-latest
86
+ needs: [test, build]
87
+ # Only publish on tagged releases
88
+ if: github.event_name == 'release' || startsWith(github.ref, 'refs/tags/')
89
+ environment:
90
+ name: pypi
91
+ url: https://pypi.org/project/nui-lambda-shared-utils/
92
+
93
+ permissions:
94
+ id-token: write # For trusted publishing
95
+ contents: read
96
+
97
+ steps:
98
+ - name: Download artifacts
99
+ uses: actions/download-artifact@v4
100
+ with:
101
+ name: dist
102
+ path: dist/
103
+
104
+ - name: Publish to PyPI
105
+ uses: pypa/gh-action-pypi-publish@release/v1
106
+ with:
107
+ verbose: true
108
+ print-hash: true
109
+
110
+ publish-test:
111
+ name: Publish to TestPyPI
112
+ runs-on: ubuntu-latest
113
+ needs: [test, build]
114
+ # Publish to TestPyPI on manual trigger or development branches
115
+ if: github.event_name == 'workflow_dispatch' || (github.event_name == 'push' && !startsWith(github.ref, 'refs/tags/'))
116
+ environment:
117
+ name: testpypi
118
+ url: https://test.pypi.org/project/nui-lambda-shared-utils/
119
+
120
+ permissions:
121
+ id-token: write
122
+ contents: read
123
+
124
+ steps:
125
+ - name: Download artifacts
126
+ uses: actions/download-artifact@v4
127
+ with:
128
+ name: dist
129
+ path: dist/
130
+
131
+ - name: Publish to TestPyPI
132
+ uses: pypa/gh-action-pypi-publish@release/v1
133
+ with:
134
+ repository-url: https://test.pypi.org/legacy/
135
+ verbose: true
136
+ print-hash: true
@@ -0,0 +1,44 @@
1
+ name: Tests
2
+
3
+ on:
4
+ push:
5
+ branches: [ main, master ]
6
+ pull_request:
7
+ branches: [ main, master ]
8
+
9
+ jobs:
10
+ test:
11
+ runs-on: ubuntu-latest
12
+ strategy:
13
+ matrix:
14
+ python-version: ['3.9', '3.10', '3.11']
15
+
16
+ steps:
17
+ - uses: actions/checkout@v3
18
+
19
+ - name: Set up Python ${{ matrix.python-version }}
20
+ uses: actions/setup-python@v4
21
+ with:
22
+ python-version: ${{ matrix.python-version }}
23
+
24
+ - name: Install dependencies
25
+ run: |
26
+ python -m pip install --upgrade pip
27
+ pip install -r requirements-test.txt
28
+ pip install -e .
29
+
30
+ - name: Check formatting with black
31
+ run: |
32
+ black --check --diff nui_lambda_shared_utils tests || {
33
+ echo "::warning::Code formatting issues found - run 'black nui_lambda_shared_utils tests' locally"
34
+ echo "Continuing build despite formatting issues..."
35
+ }
36
+
37
+ # TODO: Re-enable mypy after fixing type annotations
38
+ # - name: Type check with mypy
39
+ # run: |
40
+ # mypy lambda_shared_utils/ --config-file mypy.ini
41
+
42
+ - name: Test with pytest
43
+ run: |
44
+ pytest --cov=nui_lambda_shared_utils --cov-report=xml
@@ -0,0 +1,218 @@
1
+ # CLAUDE.md
2
+
3
+ This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
4
+
5
+ ## Project Overview
6
+
7
+ This is `nui-lambda-shared-utils`, a Python package providing enterprise-grade utilities for AWS Lambda functions. It offers standardized integrations for Slack, Elasticsearch, database operations, CloudWatch metrics, and error handling patterns commonly used across NUI platform Lambda services.
8
+
9
+ ## Architecture
10
+
11
+ ### Core Module Structure
12
+ - **Configuration System** (`config.py`) - Environment-aware configuration with AWS Secrets Manager integration
13
+ - **Secrets Management** (`secrets_helper.py`) - Centralized credential handling with caching
14
+ - **Slack Integration** (`slack_client.py`, `slack_formatter.py`) - Rich messaging, threading, and file uploads
15
+ - **Elasticsearch** (`es_client.py`, `es_query_builder.py`) - Query builders and health monitoring
16
+ - **Database** (`db_client.py`) - Connection pooling with retry logic
17
+ - **Metrics** (`cloudwatch_metrics.py`) - Batched CloudWatch publishing with decorators
18
+ - **Error Handling** (`error_handler.py`) - Retry patterns with exponential backoff
19
+ - **Timezone Utils** (`timezone.py`) - New Zealand timezone handling
20
+
21
+ ### Optional Dependencies
22
+ The package uses optional extras to minimize Lambda bundle size:
23
+ - `elasticsearch` - Elasticsearch client and query builders
24
+ - `database` - MySQL/PostgreSQL drivers
25
+ - `slack` - Slack SDK
26
+ - `all` - All integrations
27
+ - `dev` - Development and testing tools
28
+
29
+ ### Slack Setup Module
30
+ The `slack_setup/` submodule provides automated Slack workspace configuration:
31
+ - **Channel Creation** - Programmatic channel and permission setup
32
+ - **Template System** - YAML-based channel definitions
33
+ - **CLI Tool** - `nui-slack-setup` command for deployment
34
+
35
+ ## Development Commands
36
+
37
+ ### Environment Setup
38
+ ```bash
39
+ # Install package in development mode with all dependencies
40
+ pip install -e .[dev]
41
+
42
+ # Install with specific integrations only
43
+ pip install -e .[slack,elasticsearch]
44
+
45
+ # Set up virtual environment
46
+ python -m venv venv
47
+ source venv/bin/activate # Linux/Mac
48
+ ```
49
+
50
+ ### Testing
51
+ ```bash
52
+ # Run all tests
53
+ pytest
54
+
55
+ # Run with coverage reporting
56
+ pytest --cov=nui_lambda_shared_utils --cov-report=html
57
+
58
+ # Run only unit tests (skip integration tests requiring AWS)
59
+ pytest -m "not integration"
60
+
61
+ # Run specific test categories
62
+ pytest -m unit # Unit tests only
63
+ pytest -m integration # Integration tests only
64
+ pytest -m slow # Slow tests only
65
+
66
+ # Run single test file
67
+ pytest tests/test_slack_client.py -v
68
+ ```
69
+
70
+ ### Code Quality
71
+ ```bash
72
+ # Format code with Black (line length: 120)
73
+ black nui_lambda_shared_utils/ tests/
74
+
75
+ # Check formatting without changes
76
+ black --check nui_lambda_shared_utils/
77
+
78
+ # Type checking with MyPy
79
+ mypy nui_lambda_shared_utils/ --config-file mypy.ini
80
+
81
+ # Run linting (currently configured to use Black)
82
+ black --check nui_lambda_shared_utils/
83
+ ```
84
+
85
+ ### Package Building and Publishing
86
+ ```bash
87
+ # Build package
88
+ python -m build
89
+
90
+ # Install build tools
91
+ pip install build twine
92
+
93
+ # Publish to PyPI (requires credentials)
94
+ python -m twine upload dist/*
95
+ ```
96
+
97
+ ## Configuration Patterns
98
+
99
+ ### Environment Variables
100
+ The package expects these environment variables for runtime configuration:
101
+ - `ES_HOST` - Elasticsearch endpoint
102
+ - `ES_CREDENTIALS_SECRET` - AWS secret name for ES credentials
103
+ - `DB_CREDENTIALS_SECRET` - AWS secret name for database credentials
104
+ - `SLACK_CREDENTIALS_SECRET` - AWS secret name for Slack token
105
+ - `AWS_REGION` - AWS region for services
106
+
107
+ ### AWS Secrets Format
108
+ Secrets should follow standardized JSON structures:
109
+ ```json
110
+ // Elasticsearch
111
+ {"host": "elastic:9200", "username": "user", "password": "pass"}
112
+
113
+ // Database
114
+ {"host": "db-host", "port": 3306, "username": "user", "password": "pass", "database": "db"}
115
+
116
+ // Slack
117
+ {"bot_token": "xoxb-...", "webhook_url": "https://hooks.slack.com/..."}
118
+ ```
119
+
120
+ ### Programmatic Configuration
121
+ ```python
122
+ import nui_lambda_shared_utils as nui
123
+
124
+ # Configure specific settings
125
+ nui.configure(
126
+ es_host="localhost:9200",
127
+ slack_credentials_secret="dev/slack-token"
128
+ )
129
+
130
+ # Or use Config object
131
+ config = nui.Config(es_host="prod:9200")
132
+ nui.set_config(config)
133
+ ```
134
+
135
+ ## Common Usage Patterns
136
+
137
+ ### Error Handling with Decorators
138
+ ```python
139
+ from nui_lambda_shared_utils import with_retry, handle_lambda_error
140
+
141
+ @handle_lambda_error
142
+ @with_retry(max_attempts=3)
143
+ def lambda_handler(event, context):
144
+ # Lambda logic with automatic error handling and retries
145
+ pass
146
+ ```
147
+
148
+ ### Metrics Publishing
149
+ ```python
150
+ from nui_lambda_shared_utils import MetricsPublisher, track_lambda_performance
151
+
152
+ metrics = MetricsPublisher(namespace="MyService")
153
+
154
+ @track_lambda_performance(metrics)
155
+ def lambda_handler(event, context):
156
+ # Automatically tracked performance metrics
157
+ metrics.put_metric("ProcessedItems", len(items), "Count")
158
+ ```
159
+
160
+ ### Slack Integration
161
+ ```python
162
+ from nui_lambda_shared_utils import SlackClient, SlackBlockBuilder
163
+
164
+ slack = SlackClient()
165
+ builder = SlackBlockBuilder()
166
+
167
+ blocks = (builder
168
+ .add_header("Alert", emoji="warning")
169
+ .add_section("Status", "Error detected")
170
+ .build()
171
+ )
172
+
173
+ slack.send_message(channel="#alerts", blocks=blocks)
174
+ ```
175
+
176
+ ## Testing Strategy
177
+
178
+ ### Test Categories (pytest markers)
179
+ - `@pytest.mark.unit` - Fast unit tests with mocking
180
+ - `@pytest.mark.integration` - Tests requiring AWS services
181
+ - `@pytest.mark.slow` - Long-running tests
182
+
183
+ ### AWS Testing
184
+ Integration tests use `moto` for AWS service mocking. Some tests require real AWS credentials for full integration testing.
185
+
186
+ ### Test Structure
187
+ ```
188
+ tests/
189
+ ├── test_<module>.py # Main module tests
190
+ ├── conftest.py # Shared fixtures
191
+ └── fixtures/ # Test data files
192
+ ```
193
+
194
+ ## Package Distribution
195
+
196
+ ### Version Management
197
+ Version is defined in both `setup.py` and `pyproject.toml` and should be kept in sync. The package follows semantic versioning.
198
+
199
+ ### PyPI Publishing
200
+ The package is published to PyPI as `nui-lambda-shared-utils` with GitHub Actions automation for releases.
201
+
202
+ ### CLI Tools
203
+ The package provides `nui-slack-setup` CLI tool for Slack workspace configuration.
204
+
205
+ ## AWS Lambda Integration
206
+
207
+ ### Bundle Size Optimization
208
+ - Use specific extras (`[slack]`, `[elasticsearch]`) rather than `[all]`
209
+ - Optional imports prevent failure if dependencies aren't installed
210
+ - Core utilities work without optional dependencies
211
+
212
+ ### Lambda Layer Usage
213
+ The package is designed to work well in Lambda layers for sharing across multiple functions.
214
+
215
+ ### Environment Integration
216
+ - Automatic AWS region detection
217
+ - Secrets Manager integration with credential caching
218
+ - CloudWatch metrics with proper dimensions