# Swimmable Python SDK
[](https://pypi.org/project/swimmable-sdk/)
[](https://pypi.org/project/swimmable-sdk/)
[](https://opensource.org/licenses/MIT)
Official Python SDK for the [Swimmable API](https://swimmable.app) - Get real-time swimming conditions, water quality data, and AI-powered safety scores for beaches, lakes, and pools worldwide.
## Features
- 🏊 **Real-time Swimming Conditions** - Water temperature, weather, and safety data
- 🌊 **Enhanced Analysis** - AI-powered swimmability scores and detailed breakdowns
- 🏖️ **Global Coverage** - 15,000+ beaches, lakes, and swimming spots worldwide
- 🔒 **Type Safe** - Full type hints with comprehensive dataclass definitions
- ⚡ **Modern** - Async/await support and clean Python APIs
- 🚀 **Lightweight** - Minimal dependencies, works with Python 3.7+
- 📱 **Cross-platform** - Works on Windows, macOS, Linux, and cloud platforms
## Installation
```bash
pip install swimmable-sdk
```
```bash
poetry add swimmable-sdk
```
```bash
conda install -c conda-forge swimmable-sdk
```
## Quick Start
### Basic Usage (No API Key Required)
```python
from swimmable import SwimmableClient
client = SwimmableClient()
# Get current swimming conditions for Santa Monica Beach
conditions = client.get_conditions(lat=34.0195, lon=-118.4912)
print(f"Water temperature: {conditions.water_temperature}°C")
print(f"Air temperature: {conditions.air_temperature}°C")
print(f"Weather: {conditions.weather_description}")
```
### Enhanced Conditions with Safety Scores
```python
# Get detailed analysis with swimmability scoring
enhanced = client.get_enhanced_conditions(lat=25.7617, lon=-80.1918) # Miami Beach
print(f"Swimmability Score: {enhanced.swimmability_score}/10")
print(f"Water Quality Score: {enhanced.subscores.water_quality}/10")
print(f"Safety Rating: {enhanced.subscores.surf_hazard}/10")
# Check for any safety warnings
if enhanced.warnings:
print("⚠️ Safety Warnings:", enhanced.warnings)
```
### With API Key (For Production Use)
```python
client = SwimmableClient(api_key="your-api-key-here") # Get one at https://swimmable.app/signup
# Now you can access premium features and higher rate limits
stats = client.get_usage_stats()
print(f"API calls this month: {stats.total_requests}")
```
## API Reference
### Client Configuration
```python
from swimmable import SwimmableClient, SwimmableConfig
# Using configuration object
config = SwimmableConfig(
api_key="your-api-key",
base_url="https://api.swimmable.app", # Default
timeout=10.0, # Default timeout in seconds
headers={"Custom-Header": "value"}
)
client = SwimmableClient(config)
# Or pass parameters directly
client = SwimmableClient(
api_key="your-api-key",
timeout=15.0
)
```
### Basic Methods
#### `get_conditions(lat, lon)`
Get basic swimming conditions for a location.
```python
conditions = client.get_conditions(lat=34.0522, lon=-118.2437)
# Returns BasicConditions dataclass
print(f"Air temperature: {conditions.air_temperature}°C")
print(f"Water temperature: {conditions.water_temperature}°C")
print(f"Weather: {conditions.weather_description}")
print(f"UV index: {conditions.uv_index}")
print(f"Wind speed: {conditions.wind_speed} km/h")
print(f"Wave height: {conditions.wave_height}m")
print(f"Timestamp: {conditions.timestamp}")
```
#### `get_enhanced_conditions(lat, lon)`
Get detailed analysis with AI-powered safety scores.
```python
enhanced = client.get_enhanced_conditions(lat=21.2765, lon=-157.8281) # Waikiki Beach
print(f"Swimmability Score: {enhanced.swimmability_score}/10")
print(f"Location: {enhanced.location.name}")
print(f"Timezone: {enhanced.location.timezone}")
# Detailed subscores
print(f"Temperature Score: {enhanced.subscores.temperature}/10")
print(f"Water Quality Score: {enhanced.subscores.water_quality}/10")
print(f"Surf Hazard Score: {enhanced.subscores.surf_hazard}/10")
print(f"Weather Score: {enhanced.subscores.meteorology}/10")
# Water conditions
water = enhanced.conditions.water
print(f"Water temp: {water.temperature.value}{water.temperature.unit}")
print(f"pH level: {water.ph}")
print(f"Bacteria status: {water.bacteria.status}")
# Ocean conditions
ocean = enhanced.conditions.ocean
print(f"Wave height: {ocean.wave_height.value}{ocean.wave_height.unit}")
print(f"Rip current risk: {ocean.rip_risk}")
# Weather conditions
weather = enhanced.conditions.weather
print(f"Air temp: {weather.air_temp.value}{weather.air_temp.unit}")
print(f"Wind: {weather.wind_speed.value}{weather.wind_speed.unit} {weather.wind_direction}")
```
#### `get_spots()`
Get list of available swimming spots.
```python
spots = client.get_spots()
print(f"Found {spots.count} swimming spots")
for spot in spots.spots:
print(f"{spot.name} - {spot.region}")
print(f" Coordinates: {spot.lat}, {spot.lon}")
print(f" Description: {spot.description}")
```
### API Management (Requires API Key)
#### `get_usage_stats(days=30)`
Get your API usage statistics.
```python
stats = client.get_usage_stats(days=30) # Last 30 days
print(f"Total requests: {stats.total_requests}")
print(f"Successful requests: {stats.successful_requests}")
print(f"Error requests: {stats.error_requests}")
print(f"Average response time: {stats.avg_response_time}ms")
print("Top endpoints:")
for endpoint in stats.top_endpoints:
print(f" {endpoint.endpoint}: {endpoint.count} requests")
```
#### `get_api_keys()`
List your API keys.
```python
keys = client.get_api_keys()
for key in keys:
status = "Active" if key.is_active else "Inactive"
print(f"{key.name}: {status}")
print(f" Prefix: {key.key_prefix}")
print(f" Rate limit: {key.permissions.rate_limit}/hour")
if key.expires_at:
print(f" Expires: {key.expires_at}")
```
#### `create_api_key(key_data)`
Create a new API key.
```python
from swimmable import CreateApiKeyRequest
request = CreateApiKeyRequest(
name="My App Key",
description="API key for my swimming app",
expires_in_days=365 # Optional expiration
)
response = client.create_api_key(request)
print(f"New API key: {response.api_key}")
# ⚠️ Save this key securely - you won't see it again!
print(f"Key info: {response.api_key_record.name}")
print(f"Created: {response.api_key_record.created_at}")
```
### Utility Functions
The SDK includes helpful utility functions:
```python
from swimmable.utils import LocationUtils, ConditionsUtils, ApiKeyUtils
# Distance calculation
distance = LocationUtils.calculate_distance(
Coordinates(lat=34.0522, lon=-118.2437), # Santa Monica
Coordinates(lat=25.7617, lon=-80.1918) # Miami
)
print(f"Distance: {distance:.2f} km")
# Temperature conversion
fahrenheit = ConditionsUtils.celsius_to_fahrenheit(25)
print(f"25°C = {fahrenheit}°F")
# Safety assessment
is_safe = ConditionsUtils.is_safe_for_swimming(enhanced_conditions)
print("✅ Safe to swim" if is_safe else "⚠️ Check conditions carefully")
# API key validation
is_valid = ApiKeyUtils.validate_api_key("swm_1234567890abcdef...")
masked_key = ApiKeyUtils.mask_api_key("swm_1234567890abcdef...")
print(f"Key valid: {is_valid}")
print(f"Masked key: {masked_key}")
```
## Framework Examples
### Django Integration
```python
# views.py
from django.http import JsonResponse
from swimmable import SwimmableClient
from django.conf import settings
client = SwimmableClient(api_key=settings.SWIMMABLE_API_KEY)
def beach_conditions(request, lat, lon):
try:
conditions = client.get_conditions(lat=float(lat), lon=float(lon))
return JsonResponse({
'water_temperature': conditions.water_temperature,
'air_temperature': conditions.air_temperature,
'weather': conditions.weather_description,
'safe_to_swim': conditions.water_temperature > 18 # Basic safety check
})
except Exception as e:
return JsonResponse({'error': str(e)}, status=500)
```
### Flask API
```python
from flask import Flask, jsonify, request
from swimmable import SwimmableClient
import os
app = Flask(__name__)
client = SwimmableClient(api_key=os.getenv('SWIMMABLE_API_KEY'))
@app.route('/api/conditions')
def get_conditions():
lat = float(request.args.get('lat'))
lon = float(request.args.get('lon'))
try:
conditions = client.get_conditions(lat=lat, lon=lon)
return jsonify({
'water_temperature': conditions.water_temperature,
'air_temperature': conditions.air_temperature,
'weather_description': conditions.weather_description,
'uv_index': conditions.uv_index,
'timestamp': conditions.timestamp
})
except Exception as e:
return jsonify({'error': str(e)}), 500
if __name__ == '__main__':
app.run(debug=True)
```
### FastAPI Integration
```python
from fastapi import FastAPI, HTTPException
from swimmable import SwimmableClient, SwimmableError
from pydantic import BaseModel
import os
app = FastAPI()
client = SwimmableClient(api_key=os.getenv('SWIMMABLE_API_KEY'))
class LocationQuery(BaseModel):
lat: float
lon: float
@app.get("/conditions")
async def get_swimming_conditions(query: LocationQuery):
try:
conditions = client.get_conditions(lat=query.lat, lon=query.lon)
return {
"water_temperature": conditions.water_temperature,
"air_temperature": conditions.air_temperature,
"weather_description": conditions.weather_description,
"safe_to_swim": conditions.water_temperature > 18,
"timestamp": conditions.timestamp
}
except SwimmableError as e:
raise HTTPException(status_code=400, detail=str(e))
```
### Jupyter Notebook Analysis
```python
import matplotlib.pyplot as plt
import pandas as pd
from swimmable import SwimmableClient
client = SwimmableClient()
# Analyze conditions for multiple beaches
beaches = [
{"name": "Santa Monica", "lat": 34.0195, "lon": -118.4912},
{"name": "Miami Beach", "lat": 25.7617, "lon": -80.1918},
{"name": "Waikiki", "lat": 21.2765, "lon": -157.8281},
]
data = []
for beach in beaches:
conditions = client.get_conditions(beach["lat"], beach["lon"])
data.append({
"Beach": beach["name"],
"Water Temp": conditions.water_temperature,
"Air Temp": conditions.air_temperature,
"Wave Height": conditions.wave_height,
"UV Index": conditions.uv_index
})
df = pd.DataFrame(data)
print(df)
# Plot water temperatures
plt.figure(figsize=(10, 6))
plt.bar(df["Beach"], df["Water Temp"])
plt.title("Water Temperatures Across Beaches")
plt.ylabel("Temperature (°C)")
plt.show()
```
## Error Handling
The SDK provides specific exception types for different error scenarios:
```python
from swimmable import (
SwimmableClient,
SwimmableError,
SwimmableAPIError,
SwimmableTimeoutError,
SwimmableAuthenticationError,
SwimmableRateLimitError
)
client = SwimmableClient(api_key="your-key")
try:
conditions = client.get_conditions(lat=91, lon=0) # Invalid latitude
except SwimmableAuthenticationError as e:
print(f"Authentication failed: {e}")
except SwimmableRateLimitError as e:
print(f"Rate limit exceeded. Retry after {e.retry_after}s")
except SwimmableTimeoutError as e:
print(f"Request timed out after {e.timeout}s")
except SwimmableAPIError as e:
print(f"API error {e.status_code}: {e.message}")
except SwimmableError as e:
print(f"General error: {e}")
```
## Rate Limiting
The SDK includes built-in rate limiting utilities:
```python
from swimmable.utils import RateLimiter
limiter = RateLimiter(max_requests=100, window_seconds=60) # 100 requests per minute
def make_safe_request(lat, lon):
if not limiter.can_make_request():
reset_time = limiter.get_reset_time()
raise Exception(f"Rate limit exceeded. Try again in {reset_time:.1f}s")
conditions = client.get_conditions(lat=lat, lon=lon)
limiter.record_request()
return conditions
```
## Type Hints and IDE Support
The SDK is fully typed and provides excellent IDE support:
```python
from swimmable import SwimmableClient, BasicConditions, EnhancedConditions
client: SwimmableClient = SwimmableClient(api_key="your-key")
# IDE will provide autocompletion and type checking
conditions: BasicConditions = client.get_conditions(34.0522, -118.2437)
enhanced: EnhancedConditions = client.get_enhanced_conditions(34.0522, -118.2437)
# All dataclass fields are typed
water_temp: float = conditions.water_temperature
score: float = enhanced.swimmability_score
location_name: str = enhanced.location.name
```
## Testing
The SDK is designed to be easily testable:
```python
import pytest
from unittest.mock import Mock, patch
from swimmable import SwimmableClient, BasicConditions
def test_get_conditions():
client = SwimmableClient()
# Mock the API response
mock_response = {
'airTemperature': 22.5,
'waterTemperature': 20.1,
'weatherDescription': 'sunny',
'uvIndex': 6.0,
'windSpeed': 15.2,
'waveHeight': 1.2,
'timestamp': '2024-01-15T10:30:00Z'
}
with patch.object(client, '_make_request', return_value=mock_response):
conditions = client.get_conditions(34.0522, -118.2437)
assert isinstance(conditions, BasicConditions)
assert conditions.water_temperature == 20.1
assert conditions.weather_description == 'sunny'
```
## API Key Management
1. **Get an API Key**: Sign up at [swimmable.app/signup](https://swimmable.app/signup)
2. **Environment Variables**: Store your API key securely
```bash
export SWIMMABLE_API_KEY=your-api-key-here
```
3. **Rate Limits**: Free tier includes generous limits, paid plans available
4. **Security**: Never expose API keys in source code or logs
## Development
To contribute to the SDK:
```bash
# Clone the repository
git clone https://github.com/swimmable/python-sdk
cd python-sdk
# Install in development mode
pip install -e ".[dev]"
# Run tests
pytest
# Run type checking
mypy src/swimmable
# Format code
black src/ tests/
isort src/ tests/
```
## Changelog
### v1.0.0
- Initial release with full API coverage
- Complete type hints and dataclass support
- Comprehensive error handling
- Rate limiting utilities
- Framework integration examples
## Contributing
We welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md).
## Support
- 📧 **Email**: [developers@swimmable.app](mailto:developers@swimmable.app)
- 📖 **Documentation**: [swimmable.app/docs](https://swimmable.app/docs)
- 🐛 **Issues**: [GitHub Issues](https://github.com/swimmable/python-sdk/issues)
- 💬 **Community**: [Discord](https://discord.gg/swimmable)
## License
MIT License - see [LICENSE](LICENSE) file for details.
---
Built with ❤️ by the [Swimmable](https://swimmable.app) team. Making water activities safer worldwide! 🏊♀️🌊
Raw data
{
"_id": null,
"home_page": "https://github.com/swimmable/python-sdk",
"name": "swimmable-sdk",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.7",
"maintainer_email": null,
"keywords": "swimming water quality weather API ocean beach lake safety conditions",
"author": "Swimmable",
"author_email": "developers@swimmable.app",
"download_url": "https://files.pythonhosted.org/packages/6e/29/94abc41ae08d3b17967e7bbf20b663f8a053fa3fb7937b2815b7796040c3/swimmable_sdk-1.0.0.tar.gz",
"platform": null,
"description": "# Swimmable Python SDK\n\n[](https://pypi.org/project/swimmable-sdk/)\n[](https://pypi.org/project/swimmable-sdk/)\n[](https://opensource.org/licenses/MIT)\n\nOfficial Python SDK for the [Swimmable API](https://swimmable.app) - Get real-time swimming conditions, water quality data, and AI-powered safety scores for beaches, lakes, and pools worldwide.\n\n## Features\n\n- \ud83c\udfca **Real-time Swimming Conditions** - Water temperature, weather, and safety data\n- \ud83c\udf0a **Enhanced Analysis** - AI-powered swimmability scores and detailed breakdowns \n- \ud83c\udfd6\ufe0f **Global Coverage** - 15,000+ beaches, lakes, and swimming spots worldwide\n- \ud83d\udd12 **Type Safe** - Full type hints with comprehensive dataclass definitions\n- \u26a1 **Modern** - Async/await support and clean Python APIs\n- \ud83d\ude80 **Lightweight** - Minimal dependencies, works with Python 3.7+\n- \ud83d\udcf1 **Cross-platform** - Works on Windows, macOS, Linux, and cloud platforms\n\n## Installation\n\n```bash\npip install swimmable-sdk\n```\n\n```bash\npoetry add swimmable-sdk\n```\n\n```bash\nconda install -c conda-forge swimmable-sdk\n```\n\n## Quick Start\n\n### Basic Usage (No API Key Required)\n\n```python\nfrom swimmable import SwimmableClient\n\nclient = SwimmableClient()\n\n# Get current swimming conditions for Santa Monica Beach\nconditions = client.get_conditions(lat=34.0195, lon=-118.4912)\n\nprint(f\"Water temperature: {conditions.water_temperature}\u00b0C\")\nprint(f\"Air temperature: {conditions.air_temperature}\u00b0C\")\nprint(f\"Weather: {conditions.weather_description}\")\n```\n\n### Enhanced Conditions with Safety Scores\n\n```python\n# Get detailed analysis with swimmability scoring\nenhanced = client.get_enhanced_conditions(lat=25.7617, lon=-80.1918) # Miami Beach\n\nprint(f\"Swimmability Score: {enhanced.swimmability_score}/10\")\nprint(f\"Water Quality Score: {enhanced.subscores.water_quality}/10\")\nprint(f\"Safety Rating: {enhanced.subscores.surf_hazard}/10\")\n\n# Check for any safety warnings\nif enhanced.warnings:\n print(\"\u26a0\ufe0f Safety Warnings:\", enhanced.warnings)\n```\n\n### With API Key (For Production Use)\n\n```python\nclient = SwimmableClient(api_key=\"your-api-key-here\") # Get one at https://swimmable.app/signup\n\n# Now you can access premium features and higher rate limits\nstats = client.get_usage_stats()\nprint(f\"API calls this month: {stats.total_requests}\")\n```\n\n## API Reference\n\n### Client Configuration\n\n```python\nfrom swimmable import SwimmableClient, SwimmableConfig\n\n# Using configuration object\nconfig = SwimmableConfig(\n api_key=\"your-api-key\",\n base_url=\"https://api.swimmable.app\", # Default\n timeout=10.0, # Default timeout in seconds\n headers={\"Custom-Header\": \"value\"}\n)\nclient = SwimmableClient(config)\n\n# Or pass parameters directly\nclient = SwimmableClient(\n api_key=\"your-api-key\",\n timeout=15.0\n)\n```\n\n### Basic Methods\n\n#### `get_conditions(lat, lon)`\n\nGet basic swimming conditions for a location.\n\n```python\nconditions = client.get_conditions(lat=34.0522, lon=-118.2437)\n\n# Returns BasicConditions dataclass\nprint(f\"Air temperature: {conditions.air_temperature}\u00b0C\")\nprint(f\"Water temperature: {conditions.water_temperature}\u00b0C\")\nprint(f\"Weather: {conditions.weather_description}\")\nprint(f\"UV index: {conditions.uv_index}\")\nprint(f\"Wind speed: {conditions.wind_speed} km/h\")\nprint(f\"Wave height: {conditions.wave_height}m\")\nprint(f\"Timestamp: {conditions.timestamp}\")\n```\n\n#### `get_enhanced_conditions(lat, lon)`\n\nGet detailed analysis with AI-powered safety scores.\n\n```python\nenhanced = client.get_enhanced_conditions(lat=21.2765, lon=-157.8281) # Waikiki Beach\n\nprint(f\"Swimmability Score: {enhanced.swimmability_score}/10\")\nprint(f\"Location: {enhanced.location.name}\")\nprint(f\"Timezone: {enhanced.location.timezone}\")\n\n# Detailed subscores\nprint(f\"Temperature Score: {enhanced.subscores.temperature}/10\")\nprint(f\"Water Quality Score: {enhanced.subscores.water_quality}/10\")\nprint(f\"Surf Hazard Score: {enhanced.subscores.surf_hazard}/10\")\nprint(f\"Weather Score: {enhanced.subscores.meteorology}/10\")\n\n# Water conditions\nwater = enhanced.conditions.water\nprint(f\"Water temp: {water.temperature.value}{water.temperature.unit}\")\nprint(f\"pH level: {water.ph}\")\nprint(f\"Bacteria status: {water.bacteria.status}\")\n\n# Ocean conditions\nocean = enhanced.conditions.ocean\nprint(f\"Wave height: {ocean.wave_height.value}{ocean.wave_height.unit}\")\nprint(f\"Rip current risk: {ocean.rip_risk}\")\n\n# Weather conditions\nweather = enhanced.conditions.weather\nprint(f\"Air temp: {weather.air_temp.value}{weather.air_temp.unit}\")\nprint(f\"Wind: {weather.wind_speed.value}{weather.wind_speed.unit} {weather.wind_direction}\")\n```\n\n#### `get_spots()`\n\nGet list of available swimming spots.\n\n```python\nspots = client.get_spots()\nprint(f\"Found {spots.count} swimming spots\")\n\nfor spot in spots.spots:\n print(f\"{spot.name} - {spot.region}\")\n print(f\" Coordinates: {spot.lat}, {spot.lon}\")\n print(f\" Description: {spot.description}\")\n```\n\n### API Management (Requires API Key)\n\n#### `get_usage_stats(days=30)`\n\nGet your API usage statistics.\n\n```python\nstats = client.get_usage_stats(days=30) # Last 30 days\nprint(f\"Total requests: {stats.total_requests}\")\nprint(f\"Successful requests: {stats.successful_requests}\")\nprint(f\"Error requests: {stats.error_requests}\")\nprint(f\"Average response time: {stats.avg_response_time}ms\")\n\nprint(\"Top endpoints:\")\nfor endpoint in stats.top_endpoints:\n print(f\" {endpoint.endpoint}: {endpoint.count} requests\")\n```\n\n#### `get_api_keys()`\n\nList your API keys.\n\n```python\nkeys = client.get_api_keys()\nfor key in keys:\n status = \"Active\" if key.is_active else \"Inactive\"\n print(f\"{key.name}: {status}\")\n print(f\" Prefix: {key.key_prefix}\")\n print(f\" Rate limit: {key.permissions.rate_limit}/hour\")\n if key.expires_at:\n print(f\" Expires: {key.expires_at}\")\n```\n\n#### `create_api_key(key_data)`\n\nCreate a new API key.\n\n```python\nfrom swimmable import CreateApiKeyRequest\n\nrequest = CreateApiKeyRequest(\n name=\"My App Key\",\n description=\"API key for my swimming app\",\n expires_in_days=365 # Optional expiration\n)\n\nresponse = client.create_api_key(request)\nprint(f\"New API key: {response.api_key}\")\n# \u26a0\ufe0f Save this key securely - you won't see it again!\n\nprint(f\"Key info: {response.api_key_record.name}\")\nprint(f\"Created: {response.api_key_record.created_at}\")\n```\n\n### Utility Functions\n\nThe SDK includes helpful utility functions:\n\n```python\nfrom swimmable.utils import LocationUtils, ConditionsUtils, ApiKeyUtils\n\n# Distance calculation\ndistance = LocationUtils.calculate_distance(\n Coordinates(lat=34.0522, lon=-118.2437), # Santa Monica\n Coordinates(lat=25.7617, lon=-80.1918) # Miami\n)\nprint(f\"Distance: {distance:.2f} km\")\n\n# Temperature conversion\nfahrenheit = ConditionsUtils.celsius_to_fahrenheit(25)\nprint(f\"25\u00b0C = {fahrenheit}\u00b0F\")\n\n# Safety assessment\nis_safe = ConditionsUtils.is_safe_for_swimming(enhanced_conditions)\nprint(\"\u2705 Safe to swim\" if is_safe else \"\u26a0\ufe0f Check conditions carefully\")\n\n# API key validation\nis_valid = ApiKeyUtils.validate_api_key(\"swm_1234567890abcdef...\")\nmasked_key = ApiKeyUtils.mask_api_key(\"swm_1234567890abcdef...\")\nprint(f\"Key valid: {is_valid}\")\nprint(f\"Masked key: {masked_key}\")\n```\n\n## Framework Examples\n\n### Django Integration\n\n```python\n# views.py\nfrom django.http import JsonResponse\nfrom swimmable import SwimmableClient\nfrom django.conf import settings\n\nclient = SwimmableClient(api_key=settings.SWIMMABLE_API_KEY)\n\ndef beach_conditions(request, lat, lon):\n try:\n conditions = client.get_conditions(lat=float(lat), lon=float(lon))\n return JsonResponse({\n 'water_temperature': conditions.water_temperature,\n 'air_temperature': conditions.air_temperature,\n 'weather': conditions.weather_description,\n 'safe_to_swim': conditions.water_temperature > 18 # Basic safety check\n })\n except Exception as e:\n return JsonResponse({'error': str(e)}, status=500)\n```\n\n### Flask API\n\n```python\nfrom flask import Flask, jsonify, request\nfrom swimmable import SwimmableClient\nimport os\n\napp = Flask(__name__)\nclient = SwimmableClient(api_key=os.getenv('SWIMMABLE_API_KEY'))\n\n@app.route('/api/conditions')\ndef get_conditions():\n lat = float(request.args.get('lat'))\n lon = float(request.args.get('lon'))\n \n try:\n conditions = client.get_conditions(lat=lat, lon=lon)\n return jsonify({\n 'water_temperature': conditions.water_temperature,\n 'air_temperature': conditions.air_temperature,\n 'weather_description': conditions.weather_description,\n 'uv_index': conditions.uv_index,\n 'timestamp': conditions.timestamp\n })\n except Exception as e:\n return jsonify({'error': str(e)}), 500\n\nif __name__ == '__main__':\n app.run(debug=True)\n```\n\n### FastAPI Integration\n\n```python\nfrom fastapi import FastAPI, HTTPException\nfrom swimmable import SwimmableClient, SwimmableError\nfrom pydantic import BaseModel\nimport os\n\napp = FastAPI()\nclient = SwimmableClient(api_key=os.getenv('SWIMMABLE_API_KEY'))\n\nclass LocationQuery(BaseModel):\n lat: float\n lon: float\n\n@app.get(\"/conditions\")\nasync def get_swimming_conditions(query: LocationQuery):\n try:\n conditions = client.get_conditions(lat=query.lat, lon=query.lon)\n return {\n \"water_temperature\": conditions.water_temperature,\n \"air_temperature\": conditions.air_temperature,\n \"weather_description\": conditions.weather_description,\n \"safe_to_swim\": conditions.water_temperature > 18,\n \"timestamp\": conditions.timestamp\n }\n except SwimmableError as e:\n raise HTTPException(status_code=400, detail=str(e))\n```\n\n### Jupyter Notebook Analysis\n\n```python\nimport matplotlib.pyplot as plt\nimport pandas as pd\nfrom swimmable import SwimmableClient\n\nclient = SwimmableClient()\n\n# Analyze conditions for multiple beaches\nbeaches = [\n {\"name\": \"Santa Monica\", \"lat\": 34.0195, \"lon\": -118.4912},\n {\"name\": \"Miami Beach\", \"lat\": 25.7617, \"lon\": -80.1918},\n {\"name\": \"Waikiki\", \"lat\": 21.2765, \"lon\": -157.8281},\n]\n\ndata = []\nfor beach in beaches:\n conditions = client.get_conditions(beach[\"lat\"], beach[\"lon\"])\n data.append({\n \"Beach\": beach[\"name\"],\n \"Water Temp\": conditions.water_temperature,\n \"Air Temp\": conditions.air_temperature,\n \"Wave Height\": conditions.wave_height,\n \"UV Index\": conditions.uv_index\n })\n\ndf = pd.DataFrame(data)\nprint(df)\n\n# Plot water temperatures\nplt.figure(figsize=(10, 6))\nplt.bar(df[\"Beach\"], df[\"Water Temp\"])\nplt.title(\"Water Temperatures Across Beaches\")\nplt.ylabel(\"Temperature (\u00b0C)\")\nplt.show()\n```\n\n## Error Handling\n\nThe SDK provides specific exception types for different error scenarios:\n\n```python\nfrom swimmable import (\n SwimmableClient, \n SwimmableError, \n SwimmableAPIError,\n SwimmableTimeoutError,\n SwimmableAuthenticationError,\n SwimmableRateLimitError\n)\n\nclient = SwimmableClient(api_key=\"your-key\")\n\ntry:\n conditions = client.get_conditions(lat=91, lon=0) # Invalid latitude\nexcept SwimmableAuthenticationError as e:\n print(f\"Authentication failed: {e}\")\nexcept SwimmableRateLimitError as e:\n print(f\"Rate limit exceeded. Retry after {e.retry_after}s\")\nexcept SwimmableTimeoutError as e:\n print(f\"Request timed out after {e.timeout}s\")\nexcept SwimmableAPIError as e:\n print(f\"API error {e.status_code}: {e.message}\")\nexcept SwimmableError as e:\n print(f\"General error: {e}\")\n```\n\n## Rate Limiting\n\nThe SDK includes built-in rate limiting utilities:\n\n```python\nfrom swimmable.utils import RateLimiter\n\nlimiter = RateLimiter(max_requests=100, window_seconds=60) # 100 requests per minute\n\ndef make_safe_request(lat, lon):\n if not limiter.can_make_request():\n reset_time = limiter.get_reset_time()\n raise Exception(f\"Rate limit exceeded. Try again in {reset_time:.1f}s\")\n \n conditions = client.get_conditions(lat=lat, lon=lon)\n limiter.record_request()\n \n return conditions\n```\n\n## Type Hints and IDE Support\n\nThe SDK is fully typed and provides excellent IDE support:\n\n```python\nfrom swimmable import SwimmableClient, BasicConditions, EnhancedConditions\n\nclient: SwimmableClient = SwimmableClient(api_key=\"your-key\")\n\n# IDE will provide autocompletion and type checking\nconditions: BasicConditions = client.get_conditions(34.0522, -118.2437)\nenhanced: EnhancedConditions = client.get_enhanced_conditions(34.0522, -118.2437)\n\n# All dataclass fields are typed\nwater_temp: float = conditions.water_temperature\nscore: float = enhanced.swimmability_score\nlocation_name: str = enhanced.location.name\n```\n\n## Testing\n\nThe SDK is designed to be easily testable:\n\n```python\nimport pytest\nfrom unittest.mock import Mock, patch\nfrom swimmable import SwimmableClient, BasicConditions\n\ndef test_get_conditions():\n client = SwimmableClient()\n \n # Mock the API response\n mock_response = {\n 'airTemperature': 22.5,\n 'waterTemperature': 20.1,\n 'weatherDescription': 'sunny',\n 'uvIndex': 6.0,\n 'windSpeed': 15.2,\n 'waveHeight': 1.2,\n 'timestamp': '2024-01-15T10:30:00Z'\n }\n \n with patch.object(client, '_make_request', return_value=mock_response):\n conditions = client.get_conditions(34.0522, -118.2437)\n \n assert isinstance(conditions, BasicConditions)\n assert conditions.water_temperature == 20.1\n assert conditions.weather_description == 'sunny'\n```\n\n## API Key Management\n\n1. **Get an API Key**: Sign up at [swimmable.app/signup](https://swimmable.app/signup)\n2. **Environment Variables**: Store your API key securely\n ```bash\n export SWIMMABLE_API_KEY=your-api-key-here\n ```\n3. **Rate Limits**: Free tier includes generous limits, paid plans available\n4. **Security**: Never expose API keys in source code or logs\n\n## Development\n\nTo contribute to the SDK:\n\n```bash\n# Clone the repository\ngit clone https://github.com/swimmable/python-sdk\ncd python-sdk\n\n# Install in development mode\npip install -e \".[dev]\"\n\n# Run tests\npytest\n\n# Run type checking\nmypy src/swimmable\n\n# Format code\nblack src/ tests/\nisort src/ tests/\n```\n\n## Changelog\n\n### v1.0.0\n- Initial release with full API coverage\n- Complete type hints and dataclass support\n- Comprehensive error handling\n- Rate limiting utilities\n- Framework integration examples\n\n## Contributing\n\nWe welcome contributions! Please see our [Contributing Guide](CONTRIBUTING.md).\n\n## Support\n\n- \ud83d\udce7 **Email**: [developers@swimmable.app](mailto:developers@swimmable.app)\n- \ud83d\udcd6 **Documentation**: [swimmable.app/docs](https://swimmable.app/docs)\n- \ud83d\udc1b **Issues**: [GitHub Issues](https://github.com/swimmable/python-sdk/issues)\n- \ud83d\udcac **Community**: [Discord](https://discord.gg/swimmable)\n\n## License\n\nMIT License - see [LICENSE](LICENSE) file for details.\n\n---\n\nBuilt with \u2764\ufe0f by the [Swimmable](https://swimmable.app) team. Making water activities safer worldwide! \ud83c\udfca\u200d\u2640\ufe0f\ud83c\udf0a\n",
"bugtrack_url": null,
"license": null,
"summary": "Official Python SDK for the Swimmable API - Real-time swimming conditions and water quality data",
"version": "1.0.0",
"project_urls": {
"Documentation": "https://swimmable.app/docs",
"Homepage": "https://swimmable.app",
"Source": "https://github.com/swimmable/python-sdk",
"Tracker": "https://github.com/swimmable/python-sdk/issues"
},
"split_keywords": [
"swimming",
"water",
"quality",
"weather",
"api",
"ocean",
"beach",
"lake",
"safety",
"conditions"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "f8f68a941fae291c661e400cbabcdda0147062c1b68d6f0ba4217d698984c048",
"md5": "7310ce2c4e67363c3e6946bfaf48b417",
"sha256": "2ea3fcd1d0c6f869ea7b464bf79b7519440ff0a5bd71d2635056913902373ada"
},
"downloads": -1,
"filename": "swimmable_sdk-1.0.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "7310ce2c4e67363c3e6946bfaf48b417",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.7",
"size": 18696,
"upload_time": "2025-07-29T13:33:47",
"upload_time_iso_8601": "2025-07-29T13:33:47.683134Z",
"url": "https://files.pythonhosted.org/packages/f8/f6/8a941fae291c661e400cbabcdda0147062c1b68d6f0ba4217d698984c048/swimmable_sdk-1.0.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "6e2994abc41ae08d3b17967e7bbf20b663f8a053fa3fb7937b2815b7796040c3",
"md5": "6fdb29259291967a664abf34c4d52c6e",
"sha256": "ab684794617af2310036eb9a70c18241c215ce4c7de39bbddf0739bb98db257d"
},
"downloads": -1,
"filename": "swimmable_sdk-1.0.0.tar.gz",
"has_sig": false,
"md5_digest": "6fdb29259291967a664abf34c4d52c6e",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.7",
"size": 23296,
"upload_time": "2025-07-29T13:33:49",
"upload_time_iso_8601": "2025-07-29T13:33:49.122328Z",
"url": "https://files.pythonhosted.org/packages/6e/29/94abc41ae08d3b17967e7bbf20b663f8a053fa3fb7937b2815b7796040c3/swimmable_sdk-1.0.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-07-29 13:33:49",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "swimmable",
"github_project": "python-sdk",
"github_not_found": true,
"lcname": "swimmable-sdk"
}