Update code base
This commit is contained in:
parent
a60a259d4d
commit
46a5b5c039
30
.drone.yml
Normal file
30
.drone.yml
Normal file
@ -0,0 +1,30 @@
|
||||
kind: pipeline
|
||||
type: docker
|
||||
name: default
|
||||
steps:
|
||||
- name: container-build
|
||||
image: 'docker:dind'
|
||||
environment:
|
||||
USERNAME:
|
||||
from_secret: docker_username
|
||||
PASSWORD:
|
||||
from_secret: docker_password
|
||||
volumes:
|
||||
- name: dockersock
|
||||
path: /var/run/docker.sock
|
||||
commands:
|
||||
- >-
|
||||
if [ "${DRONE_BRANCH}" = "main" ]; then export
|
||||
BUILD_TAG="latest"; else export BUILD_TAG="${DRONE_BRANCH}"; fi;
|
||||
- docker login -u $USERNAME -p $PASSWORD git.argideli.com
|
||||
- >-
|
||||
docker build -t
|
||||
git.argideli.com/${DRONE_REPO_NAMESPACE}/${DRONE_REPO_NAME}:$BUILD_TAG
|
||||
.
|
||||
- >-
|
||||
docker push
|
||||
git.argideli.com/${DRONE_REPO_NAMESPACE}/${DRONE_REPO_NAME}:$BUILD_TAG
|
||||
volumes:
|
||||
- name: dockersock
|
||||
host:
|
||||
path: /var/run/docker.sock
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -9,6 +9,8 @@ __pycache__/
|
||||
|
||||
# Distribution / packaging
|
||||
.Python
|
||||
env/
|
||||
venv/
|
||||
build/
|
||||
develop-eggs/
|
||||
dist/
|
||||
@ -160,3 +162,8 @@ cython_debug/
|
||||
# option (not recommended) you can uncomment the following to ignore the entire idea folder.
|
||||
#.idea/
|
||||
|
||||
.vscode
|
||||
.vscode/
|
||||
.cache.sqlite
|
||||
.env
|
||||
requirements-old.txt
|
||||
|
25
Dockerfile
Normal file
25
Dockerfile
Normal file
@ -0,0 +1,25 @@
|
||||
# Use the official Python base image
|
||||
FROM python:3.11-slim-buster
|
||||
|
||||
# Set the working directory inside the container
|
||||
WORKDIR /code
|
||||
|
||||
# Copy the requirements file to the working directory
|
||||
COPY ./requirements.txt /code/requirements.txt
|
||||
|
||||
# Install the Python dependencies
|
||||
RUN pip config --user set global.progress_bar off
|
||||
RUN pip install --no-cache-dir --prefer-binary -r /code/requirements.txt
|
||||
|
||||
# Copy the application code to the working directory
|
||||
COPY ./*.py /code/
|
||||
COPY ./table_data /code/table_data
|
||||
COPY ./dot_env /code/.env
|
||||
|
||||
|
||||
# Expose the port on which the application will run
|
||||
EXPOSE 80
|
||||
|
||||
# Run the FastAPI application using uvicorn server
|
||||
#CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "80"]
|
||||
CMD ["uvicorn", "main:app", "--proxy-headers", "--host", "0.0.0.0", "--port", "80"]
|
34
db_connector.py
Normal file
34
db_connector.py
Normal file
@ -0,0 +1,34 @@
|
||||
import os
|
||||
from dotenv import load_dotenv
|
||||
from sqlalchemy.orm import declarative_base
|
||||
from sqlalchemy import create_engine
|
||||
from sqlalchemy.exc import SQLAlchemyError
|
||||
from sqlalchemy.orm import scoped_session, sessionmaker
|
||||
from sqlalchemy_utils import database_exists, create_database
|
||||
|
||||
#NOTE: Load environment variables from .env file
|
||||
load_dotenv()
|
||||
DATABASE = os.getenv('DATABASE')
|
||||
DB_HOST = os.getenv('DB_HOST')
|
||||
DB_USER = os.getenv('DB_USER')
|
||||
DB_PASS = os.getenv('DB_PASS')
|
||||
|
||||
DB_URI="postgresql://{}:{}@{}/{}".format(DB_USER, DB_PASS, DB_HOST, DATABASE) #, echo=True)
|
||||
|
||||
|
||||
engine=create_engine(DB_URI)
|
||||
|
||||
database=declarative_base()
|
||||
|
||||
db_session=scoped_session(sessionmaker(bind=engine))
|
||||
|
||||
if not database_exists(engine.url):
|
||||
create_database(engine.url)
|
||||
|
||||
try:
|
||||
connection = engine.connect()
|
||||
print("\n\t\tConnected successfully to database: {}@{}\n".format(DATABASE, DB_HOST))
|
||||
except SQLAlchemyError as err:
|
||||
print("\n\t\terror", err.__cause__, "\n")
|
||||
|
||||
|
4
dot_env
Normal file
4
dot_env
Normal file
@ -0,0 +1,4 @@
|
||||
DATABASE='weatherapp'
|
||||
DB_HOST='10.1.1.1'
|
||||
DB_USER='weatherapp'
|
||||
DB_PASS='YEj5zxBsM4pZlDG6NrX2'
|
107
main.py
Normal file
107
main.py
Normal file
@ -0,0 +1,107 @@
|
||||
from fastapi import FastAPI, status, HTTPException
|
||||
from models import Location
|
||||
from db_connector import database,engine
|
||||
import utils
|
||||
|
||||
|
||||
db_rebuild = True
|
||||
|
||||
database.metadata.drop_all(engine)
|
||||
if db_rebuild:
|
||||
utils.initialize_database()
|
||||
|
||||
app = FastAPI()
|
||||
|
||||
|
||||
def error_400_handler(return_data):
|
||||
"""
|
||||
A function that handles errors with status code 400. Takes return_data as input.
|
||||
Checks if the key 'error' exists in the data dictionary. If it does, it raises an HTTPException
|
||||
with status code 400 and the value of the 'error' key as the detail.
|
||||
"""
|
||||
|
||||
if 'error' in return_data.keys():
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_400_BAD_REQUEST,
|
||||
detail={'error': return_data['error']}
|
||||
)
|
||||
|
||||
|
||||
@app.get("/")
|
||||
async def index_response():
|
||||
return {"Status": "OK"}
|
||||
|
||||
@app.get("/locations")
|
||||
async def get_location_weather(places: str):
|
||||
"""
|
||||
A function to retrieve weather data for specified locations.
|
||||
|
||||
Parameters:
|
||||
places (str): A string containing location identifiers separated by commas.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing weather data for the specified locations.
|
||||
"""
|
||||
|
||||
#NOTE: Add option for fetching weather data for all locations, (debugging purposes)
|
||||
if places != 'all':
|
||||
places = [int(x) for x in list(places.split(","))]
|
||||
|
||||
result = utils.retrieve_weather_data(places)
|
||||
error_400_handler(result)
|
||||
return result
|
||||
|
||||
|
||||
@app.get("/locations/{id}")
|
||||
async def get_weather_by_id(id: int):
|
||||
"""
|
||||
A function that retrieves weather data for a location by its ID.
|
||||
|
||||
Parameters:
|
||||
- id: an integer representing the ID of the location
|
||||
|
||||
Returns:
|
||||
- The weather data for the specified location
|
||||
"""
|
||||
|
||||
|
||||
result = utils.retrieve_weather_data([id])
|
||||
error_400_handler(result)
|
||||
return result
|
||||
|
||||
|
||||
@app.post("/locations", status_code=status.HTTP_201_CREATED)
|
||||
async def add_location(
|
||||
name: str = None,
|
||||
longitude: float = None,
|
||||
latitude: float = None,
|
||||
):
|
||||
"""
|
||||
Add a new location to the database.
|
||||
|
||||
Parameters:
|
||||
- name (str): The name of the location.
|
||||
- longitude (float): The longitude coordinate of the location.
|
||||
- latitude (float): The latitude coordinate of the location.
|
||||
"""
|
||||
if len(name.encode('utf-8')) > 200:
|
||||
raise HTTPException(
|
||||
status_code=status.HTTP_413_REQUEST_ENTITY_TOO_LARGE,
|
||||
detail={'name': 'Name cannot be longer than 200 characters'}
|
||||
)
|
||||
else:
|
||||
utils.add_location(Location(name=name,longitude=longitude,latitude=latitude))
|
||||
|
||||
@app.delete("/locations/{id}")
|
||||
async def delete_location(id: int):
|
||||
"""
|
||||
Delete a location by its ID.
|
||||
|
||||
Parameters:
|
||||
id (int): The ID of the location to be deleted.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
utils.delete_location(id)
|
18
models.py
Normal file
18
models.py
Normal file
@ -0,0 +1,18 @@
|
||||
from sqlalchemy.sql.expression import null
|
||||
from db_connector import database
|
||||
from sqlalchemy import Integer, Column, Float, VARCHAR
|
||||
|
||||
class Location(database):
|
||||
#NOTE: Taumata longest place name on earth, 85 characters,
|
||||
# also accounting for the extended ASCII characters,
|
||||
# varchar of 200 Bytes should be enough for every use
|
||||
# case even with multiword names such as "The Big Apple"
|
||||
__tablename__='locations'
|
||||
id=Column(Integer,primary_key=True,autoincrement=True)
|
||||
name=Column(VARCHAR(200),nullable=False)
|
||||
latitude=Column(Float,nullable=False)
|
||||
longitude=Column(Float,nullable=False)
|
||||
|
||||
|
||||
def __repr__(self):
|
||||
return "id={} name={} longitude={} latitude={}".format(self.id,self.name,self.longitude,self.latitude)
|
53
pyproject.toml
Normal file
53
pyproject.toml
Normal file
@ -0,0 +1,53 @@
|
||||
[tool.ruff]
|
||||
select = [
|
||||
"E", # pycodestyle
|
||||
"F", # pyflakes
|
||||
"UP", # pyupgrade
|
||||
"I", # isort
|
||||
"COM", # flake8-commas
|
||||
"W", # pycodestyle
|
||||
]
|
||||
|
||||
fixable = ["I", "UP", "COM", "W"]
|
||||
show-fixes = true
|
||||
force-exclude = true
|
||||
line-length = 120
|
||||
target-version = "py310"
|
||||
extend-exclude = ["./alembic", "./.vscode", "./.devcontainer", "Dockerfile"]
|
||||
extend-ignore = [
|
||||
'E402',
|
||||
'E722',
|
||||
'W191',
|
||||
'W293',
|
||||
'C901'
|
||||
]
|
||||
[tool.ruff.per-file-ignores]
|
||||
"__init__.py" = ["F401"]
|
||||
|
||||
[tool.black]
|
||||
line-length = 120
|
||||
target-version = ['py310']
|
||||
include = '\.pyi?$'
|
||||
exclude = '''
|
||||
/(
|
||||
\.eggs
|
||||
| \.git
|
||||
| \.hg
|
||||
| \.mypy_cache
|
||||
| \.tox
|
||||
| \.venv
|
||||
| _build
|
||||
| buck-out
|
||||
| build
|
||||
| data
|
||||
| notebooks
|
||||
| dist
|
||||
| alembic
|
||||
| \.devcontainer
|
||||
| \.vscode
|
||||
# The following are specific to Black, you probably don't want those.
|
||||
| blib2to3
|
||||
| tests/data
|
||||
| profiling
|
||||
)/
|
||||
'''
|
41
requirements.txt
Normal file
41
requirements.txt
Normal file
@ -0,0 +1,41 @@
|
||||
annotated-types==0.6.0
|
||||
anyio==4.3.0
|
||||
attrs==23.2.0
|
||||
black==24.2.0
|
||||
cattrs==23.2.3
|
||||
certifi==2024.2.2
|
||||
charset-normalizer==3.3.2
|
||||
click==8.1.7
|
||||
fastapi==0.110.0
|
||||
flatbuffers==24.3.25
|
||||
greenlet==3.0.3
|
||||
h11==0.14.0
|
||||
idna==3.6
|
||||
mypy-extensions==1.0.0
|
||||
numpy==1.26.4
|
||||
openmeteo_requests==1.2.0
|
||||
openmeteo_sdk==1.11.3
|
||||
packaging==24.0
|
||||
pandas==2.2.1
|
||||
pathspec==0.12.1
|
||||
platformdirs==4.2.0
|
||||
psycopg2-binary==2.9.9
|
||||
pydantic==2.6.4
|
||||
pydantic_core==2.16.3
|
||||
python-dateutil==2.9.0.post0
|
||||
python-dotenv==1.0.1
|
||||
pytz==2024.1
|
||||
requests==2.31.0
|
||||
requests-cache==1.2.0
|
||||
retry-requests==2.0.0
|
||||
ruff==0.3.0
|
||||
six==1.16.0
|
||||
sniffio==1.3.1
|
||||
SQLAlchemy==2.0.29
|
||||
SQLAlchemy-Utils==0.41.2
|
||||
starlette==0.36.3
|
||||
typing_extensions==4.11.0
|
||||
tzdata==2024.1
|
||||
url-normalize==1.4.3
|
||||
urllib3==2.2.1
|
||||
uvicorn==0.27.1
|
235
table_data/locations.csv
Normal file
235
table_data/locations.csv
Normal file
@ -0,0 +1,235 @@
|
||||
Country,Capital City,Latitude,Longitude,Population,Capital Type
|
||||
Afghanistan,Kabul,34.5289,69.1725,4011770,Capital
|
||||
Albania,Tiranë (Tirana),41.3275,19.8189,475577,Capital
|
||||
Algeria,El Djazaïr (Algiers),36.7525,3.0420,2693542,Capital
|
||||
American Samoa,Pago Pago,-14.2781,-170.7025,48526,Capital
|
||||
Andorra,Andorra la Vella,42.5078,1.5211,22614,Capital
|
||||
Angola,Luanda,-8.8368,13.2343,7774200,Capital
|
||||
Anguilla,The Valley,18.2170,-63.0578,1402,Capital
|
||||
Antigua and Barbuda,St. John's,17.1172,-61.8457,20764,Capital
|
||||
Argentina,Buenos Aires,-34.6051,-58.4004,14966530,Capital
|
||||
Armenia,Yerevan,40.1820,44.5146,1080324,Capital
|
||||
Aruba,Oranjestad,12.5240,-70.0270,29877,Capital
|
||||
Australia,Canberra,-35.2835,149.1281,447692,Capital
|
||||
Austria,Wien (Vienna),48.2064,16.3707,1900547,Capital
|
||||
Azerbaijan,Baku,40.3777,49.8920,2285729,Capital
|
||||
Bahamas,Nassau,25.0582,-77.3431,279668,Capital
|
||||
Bahrain,Al-Manamah (Manama),26.2154,50.5832,564631,Capital
|
||||
Bangladesh,Dhaka,23.7104,90.4074,19578421,Capital
|
||||
Barbados,Bridgetown,13.1000,-59.6167,89201,Capital
|
||||
Belarus,Minsk,53.9000,27.5667,2004672,Capital
|
||||
Belgium,Bruxelles-Brussel,50.8467,4.3499,2049510,Capital
|
||||
Belize,Belmopan,17.2500,-88.7667,22964,Capital
|
||||
Benin,Cotonou,6.3654,2.4183,685458,Economic Capital
|
||||
Bermuda,Hamilton,32.2915,-64.7780,10073,Capital
|
||||
Bhutan,Thimphu,27.4661,89.6419,203297,Capital
|
||||
Bolivia (Plurinational State of),La Paz,-16.5000,-68.1500,1814087,Seat of Government
|
||||
Bosnia and Herzegovina,Sarajevo,43.8486,18.3564,342577,Capital
|
||||
Botswana,Gaborone,-24.6545,25.9086,269338,Capital
|
||||
Brazil,Brasília,-15.7797,-47.9297,4469585,Capital
|
||||
British Virgin Islands,Road Town,18.4167,-64.6167,15137,Capital
|
||||
Brunei Darussalam,Bandar Seri Begawan,4.9403,114.9481,40781,Capital
|
||||
Bulgaria,Sofia,42.6975,23.3242,1272418,Capital
|
||||
Burkina Faso,Ouagadougou,12.3642,-1.5383,2531381,Capital
|
||||
Burundi,Bujumbura,-3.3822,29.3644,898968,Capital
|
||||
Cabo Verde,Praia,14.9215,-23.5087,167504,Capital
|
||||
Cambodia,Phnum Pénh (Phnom Penh),11.5625,104.9160,1952329,Capital
|
||||
Cameroon,Yaoundé,3.8667,11.5167,3655656,Capital
|
||||
Canada,Ottawa-Gatineau,45.4166,-75.6980,1363159,Capital
|
||||
Caribbean Netherlands,Kralendijk,12.1500,-68.2667,11313,Capital
|
||||
Cayman Islands,George Town,19.2866,-81.3744,34875,Capital
|
||||
Central African Republic,Bangui,4.3612,18.5550,850946,Capital
|
||||
Chad,N'Djaména,12.1067,15.0444,1322679,Capital
|
||||
Channel Islands,St. Helier,49.1880,-2.1049,34386,Capital
|
||||
Channel Islands,St. Peter Port,49.4598,-2.5353,16271,Capital
|
||||
Chile,Santiago,-33.4569,-70.6483,6680371,Capital
|
||||
China,Beijing,39.9075,116.3972,19617963,Capital
|
||||
"China, Hong Kong SAR",Hong Kong,22.2796,114.1887,7428887,Capital
|
||||
"China, Macao SAR",Macao,22.2006,113.5461,632418,Capital
|
||||
"China, Taiwan Province of China",Taibei,25.0470,121.5457,2705791,Others
|
||||
Colombia,Bogotá,4.6097,-74.0818,10574409,Capital
|
||||
Comoros,Moroni,-11.7022,43.2551,62351,Capital
|
||||
Congo,Brazzaville,-4.2658,15.2832,2229693,Capital
|
||||
Cook Islands,Rarotonga,-21.2300,-159.7600,13067,Capital
|
||||
Costa Rica,San José,9.9278,-84.0807,1357745,Capital
|
||||
Côte d'Ivoire,Abidjan,5.3453,-4.0268,4920776,Administrative Capital
|
||||
Croatia,Zagreb,45.8144,15.9780,685587,Capital
|
||||
Cuba,La Habana (Havana),23.1195,-82.3785,2136468,Capital
|
||||
Curaçao,Willemstad,12.1084,-68.9335,144037,Capital
|
||||
Cyprus,Lefkosia (Nicosia),35.1595,33.3669,269469,Capital
|
||||
Czechia,Praha (Prague),50.0880,14.4208,1291552,Capital
|
||||
Dem. People's Republic of Korea,P'yongyang,39.0339,125.7543,3037862,Capital
|
||||
Democratic Republic of the Congo,Kinshasa,-4.3276,15.3136,13171256,Capital
|
||||
Denmark,København (Copenhagen),55.6759,12.5655,1320826,Capital
|
||||
Djibouti,Djibouti,11.5877,43.1447,561564,Capital
|
||||
Dominica,Roseau,15.3017,-61.3881,14942,Capital
|
||||
Dominican Republic,Santo Domingo,18.4896,-69.9018,3172152,Capital
|
||||
Ecuador,Quito,-0.2299,-78.5250,1822397,Capital
|
||||
Egypt,Al-Qahirah (Cairo),30.0392,31.2394,20076002,Capital
|
||||
El Salvador,San Salvador,13.6894,-89.1872,1106698,Capital
|
||||
Equatorial Guinea,Malabo,3.7500,8.7833,296770,Capital
|
||||
Eritrea,Asmara,15.3333,38.9333,895863,Capital
|
||||
Estonia,Tallinn,59.4370,24.7535,437027,Capital
|
||||
Ethiopia,Addis Ababa,9.0250,38.7469,4399674,Capital
|
||||
Faeroe Islands,Tórshavn,62.0097,-6.7716,20817,Capital
|
||||
Falkland Islands (Malvinas),Stanley,-51.7012,-57.8494,2269,Others
|
||||
Fiji,Suva,-18.1416,178.4415,178339,Capital
|
||||
Finland,Helsinki,60.1692,24.9402,1279096,Capital
|
||||
France,Paris,48.8534,2.3488,10900952,Capital
|
||||
French Guiana,Cayenne,4.9333,-52.3333,57506,Capital
|
||||
French Polynesia,Papeete,-17.5333,-149.5667,136005,Capital
|
||||
Gabon,Libreville,0.3925,9.4537,813489,Capital
|
||||
Gambia,Banjul,13.4531,-16.6794,437161,Capital
|
||||
Georgia,Tbilisi,41.6941,44.8337,1077333,Capital
|
||||
Germany,Berlin,52.5244,13.4105,3552123,Capital
|
||||
Ghana,Accra,5.5560,-0.1969,2439389,Capital
|
||||
Gibraltar,Gibraltar,36.1447,-5.3526,34733,Capital
|
||||
Greece,Athínai (Athens),37.9534,23.7490,3155600,Capital
|
||||
Greenland,Nuuk (Godthåb),64.1835,-51.7216,18406,Capital
|
||||
Grenada,St.George's,12.0564,-61.7485,39297,Capital
|
||||
Guadeloupe,Basse-Terre,15.9985,-61.7255,58397,Capital
|
||||
Guam,Hagåtña,13.4757,144.7489,146905,Capital
|
||||
Guatemala,Ciudad de Guatemala (Guatemala City),14.6127,-90.5307,2851104,Capital
|
||||
Guinea,Conakry,9.5716,-13.6476,1843121,Capital
|
||||
Guinea-Bissau,Bissau,11.8636,-15.5977,558399,Capital
|
||||
Guyana,Georgetown,6.8045,-58.1553,109934,Capital
|
||||
Haiti,Port-au-Prince,18.5392,-72.3350,2636763,Capital
|
||||
Holy See,Vatican City,41.9024,12.4533,801,Capital
|
||||
Honduras,Tegucigalpa,14.0818,-87.2068,1363041,Capital
|
||||
Hungary,Budapest,47.4980,19.0399,1759497,Capital
|
||||
Iceland,Reykjavík,64.1355,-21.8954,216364,Capital
|
||||
India,Delhi,28.6667,77.2167,28513682,Capital
|
||||
Indonesia,Jakarta,-6.2118,106.8416,10516927,Capital
|
||||
Iran (Islamic Republic of),Tehran,35.6944,51.4215,8895947,Capital
|
||||
Iraq,Baghdad,33.3406,44.4009,6811955,Capital
|
||||
Ireland,Dublin,53.3331,-6.2489,1201426,Capital
|
||||
Isle of Man,Douglas,54.1500,-4.4833,27171,Capital
|
||||
Israel,Jerusalem,31.7690,35.2163,907062,Capital
|
||||
Italy,Roma (Rome),41.8947,12.4811,4209710,Capital
|
||||
Jamaica,Kingston,17.9970,-76.7936,589083,Capital
|
||||
Japan,Tokyo,35.6895,139.6917,37468302,Capital
|
||||
Jordan,Amman,31.9552,35.9450,2064582,Capital
|
||||
Kazakhstan,Astana,51.1801,71.4460,1068113,Capital
|
||||
Kenya,Nairobi,-1.2833,36.8167,4385853,Capital
|
||||
Kiribati,Tarawa,1.3272,172.9813,64011,Capital
|
||||
Kuwait,Al Kuwayt (Kuwait City),29.3697,47.9783,2989270,Capital
|
||||
Kyrgyzstan,Bishkek,42.8700,74.5900,996319,Capital
|
||||
Lao People's Democratic Republic,Vientiane,17.9667,102.6000,664754,Capital
|
||||
Latvia,Riga,56.9460,24.1059,637089,Capital
|
||||
Lebanon,Bayrut (Beirut),33.9000,35.4833,2385271,Capital
|
||||
Lesotho,Maseru,-29.3167,27.4833,201851,Capital
|
||||
Liberia,Monrovia,6.3005,-10.7969,1418300,Capital
|
||||
Libya,Tarabulus (Tripoli),32.8752,13.1875,1157746,Capital
|
||||
Liechtenstein,Vaduz,47.1415,9.5215,5470,Capital
|
||||
Lithuania,Vilnius,54.6892,25.2798,536055,Capital
|
||||
Luxembourg,Luxembourg,49.6117,6.1300,119752,Capital
|
||||
Madagascar,Antananarivo,-18.9137,47.5361,3058387,Capital
|
||||
Malawi,Lilongwe,-13.9669,33.7873,1029639,Capital
|
||||
Malaysia,Kuala Lumpur,3.1412,101.6865,7563912,Capital
|
||||
Maldives,Male,4.1748,73.5089,176851,Capital
|
||||
Mali,Bamako,12.6500,-8.0000,2446749,Capital
|
||||
Malta,Valletta,35.8997,14.5147,212768,Capital
|
||||
Marshall Islands,Majuro,7.0897,171.3803,30661,Capital
|
||||
Martinique,Fort-de-France,14.6089,-61.0733,79361,Capital
|
||||
Mauritania,Nouakchott,18.0858,-15.9785,1205414,Capital
|
||||
Mauritius,Port Louis,-20.1619,57.4989,149365,Capital
|
||||
Mayotte,Mamoudzou,-12.7794,45.2272,6180,Capital
|
||||
Mexico,Ciudad de México (Mexico City),19.4273,-99.1419,21580827,Capital
|
||||
Micronesia (Fed. States of),Palikir,6.9174,158.1588,6996,Capital
|
||||
Monaco,Monaco,43.7333,7.4167,38897,Capital
|
||||
Mongolia,Ulaanbaatar,47.9077,106.8832,1520381,Capital
|
||||
Montenegro,Podgorica,42.4411,19.2636,177177,Capital
|
||||
Montserrat,Brades Estate,16.7918,-62.2106,472,Capital
|
||||
Morocco,Rabat,34.0133,-6.8326,1846661,Capital
|
||||
Mozambique,Maputo,-25.9653,32.5892,1101771,Capital
|
||||
Myanmar,Nay Pyi Taw,19.7450,96.1297,500218,Capital
|
||||
Namibia,Windhoek,-22.5594,17.0832,404280,Capital
|
||||
Nauru,Nauru,-0.5308,166.9112,11312,Capital
|
||||
Nepal,Kathmandu,27.7017,85.3206,1329732,Capital
|
||||
Netherlands,Amsterdam,52.3740,4.8897,1131690,Capital
|
||||
New Caledonia,Nouméa,-22.2763,166.4572,197787,Capital
|
||||
New Zealand,Wellington,-41.2866,174.7756,411346,Capital
|
||||
Nicaragua,Managua,12.1328,-86.2504,1047923,Capital
|
||||
Niger,Niamey,13.5137,2.1098,1213781,Capital
|
||||
Nigeria,Abuja,9.0574,7.4898,2918518,Capital
|
||||
Niue,Alofi,-19.0585,-169.9213,727,Capital
|
||||
Northern Mariana Islands,Saipan,15.2123,145.7545,50568,Capital
|
||||
Norway,Oslo,59.9127,10.7461,1012225,Capital
|
||||
Oman,Masqat (Muscat),23.6139,58.5922,1446563,Capital
|
||||
Pakistan,Islamabad,33.7035,73.0594,1061412,Capital
|
||||
Palau,Koror,7.3426,134.4789,11410,Capital
|
||||
Panama,Ciudad de Panamá (Panama City),8.9958,-79.5196,1783490,Capital
|
||||
Papua New Guinea,Port Moresby,-9.4431,147.1797,366862,Capital
|
||||
Paraguay,Asunción,-25.3007,-57.6359,3222199,Capital
|
||||
Peru,Lima,-12.0432,-77.0282,10390607,Capital
|
||||
Philippines,Manila,14.6042,120.9822,13482468,Capital
|
||||
Poland,Warszawa (Warsaw),52.2298,21.0118,1767798,Capital
|
||||
Portugal,Lisboa (Lisbon),38.7169,-9.1399,2927316,Capital
|
||||
Puerto Rico,San Juan,18.4663,-66.1057,2454337,Capital
|
||||
Qatar,Ad-Dawhah (Doha),25.2747,51.5245,633401,Capital
|
||||
Republic of Korea,Seoul,37.5683,126.9778,9963497,Capital
|
||||
Republic of Moldova,Chişinău,47.0056,28.8575,509707,Capital
|
||||
Réunion,Saint-Denis,-20.8823,55.4504,147209,Capital
|
||||
Romania,Bucuresti (Bucharest),44.4328,26.1043,1821380,Capital
|
||||
Russian Federation,Moskva (Moscow),55.7550,37.6218,12409738,Capital
|
||||
Rwanda,Kigali,-1.9474,30.0579,1057836,Capital
|
||||
Saint Helena,Jamestown,-15.9387,-5.7168,603,Capital
|
||||
Saint Kitts and Nevis,Basseterre,17.2948,-62.7261,14434,Capital
|
||||
Saint Lucia,Castries,14.0060,-60.9910,22258,Capital
|
||||
Saint Pierre and Miquelon,Saint-Pierre,46.7738,-56.1815,5723,Capital
|
||||
Saint Vincent and the Grenadines,Kingstown,13.1587,-61.2248,26636,Capital
|
||||
Samoa,Apia,-13.8333,-171.7667,36066,Capital
|
||||
San Marino,San Marino,43.9333,12.4500,4465,Capital
|
||||
Sao Tome and Principe,São Tomé,0.3365,6.7273,80099,Capital
|
||||
Saudi Arabia,Ar-Riyadh (Riyadh),24.6905,46.7096,6906595,Capital
|
||||
Senegal,Dakar,14.6937,-17.4441,2978419,Capital
|
||||
Serbia,Beograd (Belgrade),44.8176,20.4633,1389351,Capital
|
||||
Seychelles,Victoria,-4.6167,55.4500,28091,Capital
|
||||
Sierra Leone,Freetown,8.4840,-13.2299,1135949,Capital
|
||||
Singapore,Singapore,1.2897,103.8501,5791901,Capital
|
||||
Sint Maarten (Dutch part),Philipsburg,18.0260,-63.0458,40552,Capital
|
||||
Slovakia,Bratislava,48.1482,17.1067,429920,Capital
|
||||
Slovenia,Ljubljana,46.0511,14.5051,286491,Capital
|
||||
Solomon Islands,Honiara,-9.4333,159.9500,81801,Capital
|
||||
Somalia,Muqdisho (Mogadishu),2.0416,45.3435,2081624,Capital
|
||||
South Africa,Cape Town,-33.9258,18.4232,4430367,Legislative Capital
|
||||
South Sudan,Juba,4.8517,31.5825,368914,Capital
|
||||
Spain,Madrid,40.4165,-3.7026,6497124,Capital
|
||||
Sri Lanka,Colombo,6.9319,79.8478,599821,Capital
|
||||
State of Palestine,Al-Quds[East Jerusalem],31.7834,35.2339,275086,Capital
|
||||
Sudan,Al-Khartum (Khartoum),15.5518,32.5324,5534079,Capital
|
||||
Suriname,Paramaribo,5.8664,-55.1668,239457,Capital
|
||||
Swaziland,Mbabane,-26.3167,31.1333,68010,Capital
|
||||
Sweden,Stockholm,59.3326,18.0649,1582968,Capital
|
||||
Switzerland,Bern,46.9481,7.4474,422153,Capital
|
||||
Syrian Arab Republic,Dimashq (Damascus),33.5086,36.3084,2319545,Capital
|
||||
Tajikistan,Dushanbe,38.5358,68.7791,872653,Capital
|
||||
TFYR Macedonia,Skopje,42.0000,21.4333,584208,Capital
|
||||
Thailand,Krung Thep (Bangkok),13.7220,100.5252,10156316,Capital
|
||||
Timor-Leste,Dili,-8.5601,125.5668,281135,Capital
|
||||
Togo,Lomé,6.1375,1.2123,1745744,Capital
|
||||
Tokelau,Tokelau,-9.3800,-171.2500,0,Others
|
||||
Tonga,Nuku'alofa,-21.1394,-175.2032,22904,Capital
|
||||
Trinidad and Tobago,Port of Spain,10.6662,-61.5166,544417,Capital
|
||||
Tunisia,Tunis,36.8190,10.1658,2290777,Capital
|
||||
Turkey,Ankara,39.9199,32.8543,4919074,Capital
|
||||
Turkmenistan,Ashgabat,37.9500,58.3833,810186,Capital
|
||||
Turks and Caicos Islands,Cockburn Town,21.4612,-71.1419,5447,Capital
|
||||
Tuvalu,Funafuti,-8.5189,179.1991,7042,Capital
|
||||
Uganda,Kampala,0.3163,32.5822,2986352,Capital
|
||||
Ukraine,Kyiv (Kiev),50.4454,30.5186,2956706,Capital
|
||||
United Arab Emirates,Abu Zaby (Abu Dhabi),24.4648,54.3618,1419699,Capital
|
||||
United Kingdom,London,51.5085,-0.1257,9046485,Capital
|
||||
United Republic of Tanzania,Dodoma,-6.1722,35.7395,261645,Capital
|
||||
United States of America,"Washington, D.C.",38.8951,-77.0364,5206593,Capital
|
||||
United States Virgin Islands,Charlotte Amalie,18.3419,-64.9307,52322,Capital
|
||||
Uruguay,Montevideo,-34.8335,-56.1674,1736989,Capital
|
||||
Uzbekistan,Tashkent,41.2647,69.2163,2463969,Capital
|
||||
Vanuatu,Port Vila,-17.7338,168.3219,52690,Capital
|
||||
Venezuela (Bolivarian Republic of),Caracas,10.4880,-66.8792,2934560,Capital
|
||||
Viet Nam,Hà Noi,21.0245,105.8412,4282738,Capital
|
||||
Wallis and Futuna Islands,Matu-Utu,-13.2816,-176.1745,1025,Capital
|
||||
Western Sahara,El Aaiún,27.1532,-13.2014,232388,Capital
|
||||
Yemen,Sana'a',15.3531,44.2078,2779317,Capital
|
||||
Zambia,Lusaka,-15.4134,28.2771,2523844,Capital
|
||||
Zimbabwe,Harare,-17.8294,31.0539,1515016,Capital
|
|
192
utils.py
Normal file
192
utils.py
Normal file
@ -0,0 +1,192 @@
|
||||
from models import Location
|
||||
from db_connector import database,engine,db_session
|
||||
import pandas as pd
|
||||
import openmeteo_requests
|
||||
import requests_cache
|
||||
from retry_requests import retry
|
||||
|
||||
|
||||
def initialize_database():
|
||||
"""
|
||||
A function to initialize the database by checking table availability and creating it if it does not exist.
|
||||
"""
|
||||
|
||||
db_tables = ['locations']
|
||||
# check table availability and create it if it does not exist
|
||||
for tb in db_tables:
|
||||
if not engine.dialect.has_table(engine.connect(), tb):
|
||||
print("Creating table: {}\n".format(tb))
|
||||
database.metadata.create_all(engine)
|
||||
|
||||
table_data = pd.read_csv ('./table_data/locations.csv', index_col=None, header=0)
|
||||
for i in range(len(table_data)):
|
||||
add_location(Location(name=table_data.loc[i, "Capital City"],
|
||||
latitude=float(table_data.loc[i, "Latitude"]),
|
||||
longitude=float(table_data.loc[i, "Longitude"]),
|
||||
),
|
||||
no_commit=True
|
||||
)
|
||||
db_session.commit()
|
||||
|
||||
def add_location(location:Location , no_commit=False):
|
||||
"""
|
||||
A function that adds a location to the database session.
|
||||
|
||||
Parameters:
|
||||
location (Location): The location object to be added to the database session.
|
||||
no_commit (bool): Flag indicating whether to commit the transaction immediately.
|
||||
|
||||
Returns:
|
||||
None
|
||||
"""
|
||||
|
||||
db_session.add(location)
|
||||
#print("Adding location: {}".format(location))
|
||||
if not no_commit:
|
||||
db_session.commit()
|
||||
|
||||
|
||||
def delete_location(id):
|
||||
"""
|
||||
Deletes a location from the database based on the provided ID.
|
||||
|
||||
Parameters:
|
||||
id (int): The ID of the location to be deleted.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary with the key "id" indicating that the location was successfully deleted.
|
||||
"""
|
||||
|
||||
db_session.query(Location).filter(Location.id == id).delete()
|
||||
db_session.commit()
|
||||
return {"id": "Deleted"}
|
||||
|
||||
|
||||
def chunkify_data(data, chunk_size):
|
||||
"""
|
||||
A function that chunks the input data into smaller pieces of the specified chunk size.
|
||||
|
||||
Parameters:
|
||||
- data: the input data to be chunked
|
||||
- chunk_size: the size of each chunk
|
||||
|
||||
Returns:
|
||||
- A generator that yields chunks of the input data
|
||||
"""
|
||||
|
||||
for i in range(0, len(data), chunk_size):
|
||||
yield data[i:i + chunk_size]
|
||||
|
||||
|
||||
def retrieve_weather_data(location_id=None):
|
||||
"""
|
||||
A function to retrieve weather data based on location IDs.
|
||||
|
||||
Parameters:
|
||||
- location_id: an optional parameter to specify the location ID(s) to retrieve weather data for. If 'all' is provided, data for all locations is returned.
|
||||
|
||||
Returns:
|
||||
- If location_id is not 'all' and any specified location ID does not exist, a dictionary of invalid location IDs is returned.
|
||||
- If location_id is None, None is returned.
|
||||
- If location_id is 'all', weather data for all locations is returned in a dictionary.
|
||||
- Otherwise, weather data for the specified location IDs is returned in a dictionary.
|
||||
"""
|
||||
print('xaz')
|
||||
max_id = db_session.query(Location).count()
|
||||
|
||||
#NOTE: Disable location check if location_id is 'all' (returns all locations), debugging purposes
|
||||
if location_id != 'all':
|
||||
loc_check = {}
|
||||
for loc_id in location_id:
|
||||
if loc_id > max_id:
|
||||
loc_check[loc_id] = "The location does not exist"
|
||||
print(len(loc_check))
|
||||
if len(loc_check) > 0:
|
||||
return {'error': loc_check}
|
||||
|
||||
print('az')
|
||||
weather_data = {}
|
||||
|
||||
#NOTE: Get weather data for all locations if location_id is 'all' (debugging purposes), otherwise get weather data for specified locations
|
||||
if location_id == 'all':
|
||||
locations = list(chunkify_data(db_session.query(Location).all(),100))
|
||||
else:
|
||||
locations = list(chunkify_data(db_session.query(Location).filter(Location.id.in_(location_id)).all(),100))
|
||||
print(locations)
|
||||
for chunk in locations:
|
||||
coordinates = [[loc.id, loc.latitude, loc.longitude, loc.name] for loc in chunk]
|
||||
weather_data.update(get_openmeteo_data(coordinates))
|
||||
#print(weather_data)
|
||||
#exit(0)
|
||||
return weather_data
|
||||
|
||||
def get_openmeteo_data(coordinates):
|
||||
"""
|
||||
Retrieves weather data from the OpenMeteo API for the given coordinates.
|
||||
|
||||
Parameters:
|
||||
coordinates (list): List of tuples containing latitude, longitude, and location name.
|
||||
|
||||
Returns:
|
||||
dict: A dictionary containing the retrieved weather data for each location.
|
||||
"""
|
||||
|
||||
data_dict = {}
|
||||
cache_session = requests_cache.CachedSession('.cache', expire_after = 3600)
|
||||
retry_session = retry(cache_session, retries = 5, backoff_factor = 0.2)
|
||||
openmeteo_client = openmeteo_requests.Client(session = retry_session)
|
||||
|
||||
latitude = [coords[1] for coords in coordinates]
|
||||
longitude = [coords[2] for coords in coordinates]
|
||||
|
||||
# NOTE: Uncomment to get all available weather data for each location
|
||||
# data_names = [
|
||||
# "weather_code", "temperature_2m_max", "temperature_2m_min",
|
||||
# "apparent_temperature_max", "apparent_temperature_min",
|
||||
# "sunrise", "sunset", "daylight_duration", "sunshine_duration",
|
||||
# "uv_index_max", "uv_index_clear_sky_max", "precipitation_sum",
|
||||
# "rain_sum", "showers_sum", "snowfall_sum", "precipitation_hours",
|
||||
# "precipitation_probability_max", "wind_speed_10m_max",
|
||||
# "wind_gusts_10m_max", "wind_direction_10m_dominant",
|
||||
# "shortwave_radiation_sum", "et0_fao_evapotranspiration"
|
||||
# ]
|
||||
|
||||
data_names = ["temperature_2m_max", "temperature_2m_min", "precipitation_sum"]
|
||||
|
||||
#NOTE: OpenMeteo API has a limit of 10000 requests per day,
|
||||
# so in a production environment it would be wise to change to
|
||||
# an enterprise account OR utilize the clients for the requests
|
||||
url = "https://api.open-meteo.com/v1/forecast"
|
||||
params = {
|
||||
"latitude": latitude,
|
||||
"longitude": longitude,
|
||||
"daily": data_names
|
||||
}
|
||||
|
||||
responses = openmeteo_client.weather_api(url, params=params)
|
||||
|
||||
for idx, response in enumerate(responses, start=1):
|
||||
location = coordinates[idx-1][3]
|
||||
idx = coordinates[idx-1][0]
|
||||
|
||||
daily = response.Daily()
|
||||
|
||||
daily_data = { variable: daily.Variables(i).ValuesAsNumpy().tolist()
|
||||
if variable not in ["sunrise", "sunset"]
|
||||
else daily.Variables(i).ValuesAsNumpy()
|
||||
for i, variable in enumerate(data_names)
|
||||
}
|
||||
|
||||
dates = pd.date_range(start = pd.to_datetime(daily.Time(), unit = "s", utc = True),
|
||||
end = pd.to_datetime(daily.TimeEnd(), unit = "s", utc = True),
|
||||
freq = pd.Timedelta(seconds = daily.Interval()),
|
||||
inclusive = "left").tolist()
|
||||
|
||||
daily_data["date"] = [date.strftime("%d/%m/%Y") for date in dates]
|
||||
daily_data["location_name"] = location
|
||||
daily_data["resp_coordinates"] = [response.Latitude(), response.Longitude()]
|
||||
|
||||
data_dict[idx] = daily_data
|
||||
|
||||
return data_dict
|
||||
|
Loading…
x
Reference in New Issue
Block a user