generated from nogibjj/Jennifer-Li_DE-mini-project-1
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Jennifer Li
authored and
Jennifer Li
committed
Nov 26, 2024
1 parent
7db4e00
commit 427bef4
Showing
24 changed files
with
703 additions
and
113 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
# Python | ||
__pycache__ | ||
*.pyc | ||
*.pyo | ||
*.pyd | ||
.Python | ||
*.py[cod] | ||
|
||
# Environment | ||
.env | ||
venv | ||
.venv | ||
env/ | ||
ENV/ | ||
|
||
# IDE | ||
.idea | ||
.vscode | ||
*.swp | ||
*.swo | ||
|
||
# Git | ||
.git | ||
.gitignore | ||
|
||
# OS | ||
.DS_Store | ||
Thumbs.db | ||
|
||
# Testing | ||
.pytest_cache | ||
.coverage | ||
htmlcov/ | ||
|
||
# Project specific | ||
*.log | ||
local_settings.py | ||
db.sqlite3 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
name: Build and Push Docker Image | ||
|
||
on: | ||
push: | ||
branches: | ||
- main | ||
|
||
jobs: | ||
build: | ||
runs-on: ubuntu-latest | ||
|
||
steps: | ||
- name: Checkout repository | ||
uses: actions/checkout@v2 | ||
|
||
- name: Log in to Docker Hub | ||
uses: docker/login-action@v1 | ||
with: | ||
username: ${{ secrets.DOCKER_USERNAME }} | ||
password: ${{ secrets.DOCKER_PASSWORD }} | ||
|
||
- name: Build Docker image | ||
run: make build | ||
|
||
- name: Push Docker image | ||
run: make push | ||
env: | ||
DOCKER_ID_USER: ${{ secrets.DOCKER_USERNAME }} | ||
IMAGE_NAME: de_demo |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,167 @@ | ||
# api_key = "b38066974d9946f466ce5632a763aed3" | ||
|
||
import requests | ||
from datetime import datetime | ||
from statistics import mean | ||
|
||
|
||
class WeatherAPI: | ||
def __init__(self, api_key): | ||
""" | ||
Initialize WeatherAPI with your API key | ||
Sign up at: https://openweathermap.org/api to get an API key | ||
""" | ||
self.api_key = api_key | ||
self.base_url = "https://api.openweathermap.org/data/2.5" | ||
|
||
def get_current_weather(self, city): | ||
"""Get current weather for a city""" | ||
endpoint = f"{self.base_url}/weather" | ||
params = { | ||
"q": city, | ||
"appid": self.api_key, | ||
"units": "metric", # Use metric units (Celsius, meters/sec) | ||
} | ||
|
||
try: | ||
response = requests.get(endpoint, params=params) | ||
response.raise_for_status() | ||
data = response.json() | ||
|
||
if "main" not in data or "weather" not in data: | ||
raise ValueError(f"Unexpected API response format: {data}") | ||
|
||
weather_info = { | ||
"temperature": data["main"]["temp"], | ||
"feels_like": data["main"]["feels_like"], | ||
"humidity": data["main"]["humidity"], | ||
"description": data["weather"][0]["description"], | ||
"wind_speed": data["wind"]["speed"], | ||
"city": data["name"], | ||
"country": data["sys"]["country"], | ||
"sunrise": datetime.fromtimestamp(data["sys"]["sunrise"]).strftime( | ||
"%H:%M" | ||
), | ||
"sunset": datetime.fromtimestamp(data["sys"]["sunset"]).strftime( | ||
"%H:%M" | ||
), | ||
} | ||
|
||
return weather_info | ||
|
||
except requests.exceptions.RequestException as e: | ||
print(f"API Request Error: {str(e)}") | ||
return None | ||
except ValueError as e: | ||
print(f"Data Processing Error: {str(e)}") | ||
return None | ||
except Exception as e: | ||
print(f"Unexpected Error: {str(e)}") | ||
return None | ||
|
||
def get_forecast(self, city, days=5): | ||
"""Get weather forecast for specified number of days""" | ||
endpoint = f"{self.base_url}/forecast" | ||
params = {"q": city, "appid": self.api_key, "units": "metric"} | ||
|
||
try: | ||
response = requests.get(endpoint, params=params) | ||
response.raise_for_status() | ||
data = response.json() | ||
|
||
if "list" not in data: | ||
raise ValueError(f"Unexpected API response format: {data}") | ||
|
||
# Process forecast data by day | ||
daily_forecasts = {} | ||
|
||
for item in data["list"]: | ||
date = datetime.fromtimestamp(item["dt"]).strftime("%Y-%m-%d") | ||
|
||
if date not in daily_forecasts: | ||
daily_forecasts[date] = { | ||
"temperatures": [], | ||
"descriptions": [], | ||
"wind_speeds": [], | ||
} | ||
|
||
daily_forecasts[date]["temperatures"].append(item["main"]["temp"]) | ||
daily_forecasts[date]["descriptions"].append( | ||
item["weather"][0]["description"] | ||
) | ||
daily_forecasts[date]["wind_speeds"].append(item["wind"]["speed"]) | ||
|
||
# Create summary for each day | ||
forecast = [] | ||
for date, data in list(daily_forecasts.items())[:days]: | ||
# Get most common weather description for the day | ||
most_common_description = max( | ||
set(data["descriptions"]), key=data["descriptions"].count | ||
) | ||
|
||
forecast.append( | ||
{ | ||
"date": date, | ||
"avg_temp": round(mean(data["temperatures"]), 1), | ||
"max_temp": round(max(data["temperatures"]), 1), | ||
"min_temp": round(min(data["temperatures"]), 1), | ||
"description": most_common_description, | ||
"avg_wind": round(mean(data["wind_speeds"]), 1), | ||
} | ||
) | ||
|
||
return forecast | ||
|
||
except requests.exceptions.RequestException as e: | ||
print(f"API Request Error: {str(e)}") | ||
return None | ||
except ValueError as e: | ||
print(f"Data Processing Error: {str(e)}") | ||
return None | ||
except Exception as e: | ||
print(f"Unexpected Error: {str(e)}") | ||
return None | ||
|
||
|
||
# Example usage | ||
if __name__ == "__main__": | ||
# Configuration | ||
api_key = "b38066974d9946f466ce5632a763aed3" # Replace with your actual API key | ||
city_name = "San Francisco" # Replace with your desired city | ||
forecast_days = 5 # Number of days for forecast | ||
|
||
# Initialize weather API | ||
weather = WeatherAPI(api_key) | ||
|
||
# Get and display current weather | ||
current = weather.get_current_weather(city_name) | ||
if current is not None: | ||
print("\nCurrent Weather:") | ||
print(f"City: {current['city']}, {current['country']}") | ||
print(f"Temperature: {current['temperature']}°C") | ||
print(f"Feels like: {current['feels_like']}°C") | ||
print(f"Description: {current['description']}") | ||
print(f"Humidity: {current['humidity']}%") | ||
print(f"Wind Speed: {current['wind_speed']} m/s") | ||
print(f"Sunrise: {current['sunrise']}") | ||
print(f"Sunset: {current['sunset']}") | ||
else: | ||
print( | ||
"Failed to get weather data. Please check your API key and internet connection." | ||
) | ||
|
||
# Get and display forecast | ||
print(f"\n{forecast_days}-Day Weather Forecast for {city_name}:") | ||
forecast = weather.get_forecast(city_name, forecast_days) | ||
if forecast is not None: | ||
for day in forecast: | ||
print(f"\n{day['date']}:") | ||
print( | ||
f" Temperature: {day['min_temp']}°C to {day['max_temp']}°C (avg: {day['avg_temp']}°C)" | ||
) | ||
print(f" Description: {day['description']}") | ||
print(f" Wind Speed: {day['avg_wind']} m/s") | ||
else: | ||
print( | ||
"Failed to get forecast data. Please check your API key and internet connection." | ||
) |
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,4 @@ | ||
__pycache__/ | ||
.DS_Store | ||
.DS_Store | ||
*.pyc | ||
.pytest_cache/ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
# Use an official Python runtime as the base image | ||
FROM python:3.9-slim | ||
|
||
# Set the working directory in the container | ||
WORKDIR /app | ||
|
||
# Copy the requirements file into the container | ||
COPY requirements.txt . | ||
|
||
# Install the required packages | ||
RUN pip install --no-cache-dir -r requirements.txt | ||
|
||
# Copy the application code into the container | ||
COPY app.py . | ||
COPY templates/ ./templates/ | ||
|
||
# Expose the port the app runs on | ||
EXPOSE 5000 | ||
|
||
# Command to run the application using gunicorn | ||
CMD ["gunicorn", "--bind", "0.0.0.0:5000", "app:app"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,31 @@ | ||
install: | ||
pip install --upgrade pip && pip install -r requirements.txt | ||
# Makefile | ||
DOCKER_ID_USER ?= jenniferli6 | ||
IMAGE_NAME ?= de_demo | ||
VERSION ?= latest | ||
|
||
# Default target - runs when you just type 'make' | ||
.PHONY: all | ||
all: clean install test build push | ||
|
||
# Docker commands | ||
build: | ||
docker build -t $(DOCKER_ID_USER)/$(IMAGE_NAME):$(VERSION) . | ||
|
||
format: | ||
black *.py | ||
push: | ||
docker push $(DOCKER_ID_USER)/$(IMAGE_NAME):$(VERSION) | ||
|
||
run: | ||
docker run -p 5001:5000 $(DOCKER_ID_USER)/$(IMAGE_NAME):$(VERSION) | ||
|
||
# Development commands | ||
install: | ||
pip install -r requirements.txt | ||
|
||
lint: | ||
pylint --disable=R,C --ignore-patterns=test_.*?py *.py | ||
test: | ||
python -m pytest | ||
|
||
test: | ||
python -m pytest -cov=main test_main.py | ||
clean: | ||
find . -type d -name "__pycache__" -exec rm -r {} + | ||
find . -type f -name "*.pyc" -delete | ||
|
||
all: install format lint test | ||
.PHONY: build push run install test clean |
Oops, something went wrong.