weathervault
Obtain Polars DataFrames of historical weather data from NOAA's National Centers for Environmental Information (NCEI) Integrated Surface Database (ISD).
Features
- download and decode weather station data with a simple API
- get data as efficient Polars DataFrames ready for analysis
- locate met stations by name, location, and elevation
- automatic conversion from UTC to local station time
- support different temperature units (Celsius, Fahrenheit, and Kelvin)
- optional local data file caching with automatic cache detection
- access to the global ISD network of weather stations (29,000+ stations)
Installation
pip install weathervault
Quick Start
import weathervault as wv
# Get weather data for LaGuardia Airport (New York) for 2024
weather = wv.get_weather_data("725030-14732", years=2024)
weather.head()
Output:
shape: (5, 10)
┌──────────────┬─────────────────────────┬───────┬───────────┬───────┬─────┬──────┬────────────┬──────────┬────────────┐
│ id ┆ time ┆ temp ┆ dew_point ┆ rh ┆ wd ┆ ws ┆ atmos_pres ┆ ceil_hgt ┆ visibility │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ datetime[μs, tz] ┆ f64 ┆ f64 ┆ f64 ┆ i32 ┆ f64 ┆ f64 ┆ i32 ┆ i32 │
╞══════════════╪═════════════════════════╪═══════╪═══════════╪═══════╪═════╪══════╪════════════╪══════════╪════════════╡
│ 725030-14732 ┆ 2024-01-01 00:51:00 EST ┆ 12.8 ┆ 7.8 ┆ 72.1 ┆ 200 ┆ 4.6 ┆ 1016.9 ┆ 2438 ┆ 16093 │
│ 725030-14732 ┆ 2024-01-01 01:51:00 EST ┆ 12.2 ┆ 7.2 ┆ 71.8 ┆ 190 ┆ 5.1 ┆ 1016.5 ┆ 2743 ┆ 16093 │
│ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... ┆ ... │
└──────────────┴─────────────────────────┴───────┴───────────┴───────┴─────┴──────┴────────────┴──────────┴────────────┘
Finding Weather Stations
Convenient Shorthand Syntax
Use wv.country and wv.state for clean, readable code with IDE autocomplete:
# Search by country using convenient shorthand
de_stations = wv.search_stations(country_code=wv.country.DE)
de_stations.head()
Output:
shape: (5, 9)
┌──────────────┬──────────────────────────────────┬─────────────┬───────────────┬───────┬───────┬────────┬────────┬────────┐
│ id ┆ name ┆ country ┆ state ┆ icao ┆ lat ┆ lon ┆ elev ┆ begin │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪══════════════════════════════════╪═════════════╪═══════════════╪═══════╪═══════╪════════╪════════╪════════╡
│ 100040-99999 ┆ JAN MAYEN ┆ NORWAY ┆ null ┆ ENJA ┆ 70.93 ┆ -8.67 ┆ 9.0 ┆ 19210… │
│ 100050-99999 ┆ TWENTHE ┆ NETHERLANDS ┆ null ┆ EHTW ┆ 52.27 ┆ 6.89 ┆ 35.0 ┆ 19460… │
│ 100070-99999 ┆ FRIGG ┆ NORWAY ┆ null ┆ null ┆ 59.9 ┆ 2.25 ┆ 47.0 ┆ 19780… │
│ 100080-99999 ┆ EKOFISK ┆ NORWAY ┆ null ┆ EKOF ┆ 56.55 ┆ 3.22 ┆ 30.0 ┆ 19760… │
│ 100100-99999 ┆ HEIDRUN ┆ NORWAY ┆ null ┆ null ┆ 65.33 ┆ 7.32 ┆ 222.0 ┆ 19940… │
└──────────────┴──────────────────────────────────┴─────────────┴───────────────┴───────┴───────┴────────┴────────┴────────┘
# Search by US state
ca_stations = wv.search_stations(state=wv.state.CA)
ca_stations.head()
Output:
shape: (5, 9)
┌──────────────┬─────────────────────────────┬─────────┬───────┬───────┬───────┬──────────┬───────┬────────┐
│ id ┆ name ┆ country ┆ state ┆ icao ┆ lat ┆ lon ┆ elev ┆ begin │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════════════════════╪═════════╪═══════╪═══════╪═══════╪══════════╪═══════╪════════╡
│ 690020-99999 ┆ NORTH ISLAND ┆ US ┆ CA ┆ KNZY ┆ 32.7 ┆ -117.21 ┆ 8.0 ┆ 19730… │
│ 690150-23174 ┆ TWENTYNINE PALMS ┆ US ┆ CA ┆ KNXP ┆ 34.3 ┆ -116.15 ┆ 626.0 ┆ 19420… │
│ 690190-93134 ┆ IMPERIAL BEACH ┆ US ┆ CA ┆ KNRS ┆ 32.57 ┆ -117.12 ┆ 6.0 ┆ 19580… │
│ 690230-23188 ┆ EDWARDS AFB ┆ US ┆ CA ┆ KEDW ┆ 34.9 ┆ -117.88 ┆ 702.0 ┆ 19420… │
│ 690240-99999 ┆ VANDENBERG SFB ┆ US ┆ CA ┆ KVBG ┆ 34.73 ┆ -120.57 ┆ 112.0 ┆ 19730… │
└──────────────┴─────────────────────────────┴─────────┴───────┴───────┴───────┴──────────┴───────┴────────┘
Search by Location (lat/long Bounding Box)
# Search by coordinates (latitude/longitude range)
nyc_stations = wv.search_stations(
lat_range=(40.5, 41.0),
lon_range=(-74.5, -73.5)
)
nyc_stations
Output:
shape: (8, 9)
┌──────────────┬───────────────────────────────┬─────────┬───────┬───────┬───────┬─────────┬───────┬────────┐
│ id ┆ name ┆ country ┆ state ┆ icao ┆ lat ┆ lon ┆ elev ┆ begin │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═══════════════════════════════╪═════════╪═══════╪═══════╪═══════╪═════════╪═══════╪════════╡
│ 725020-14734 ┆ NEWARK LIBERTY INTERNATIONAL ┆ US ┆ NJ ┆ KEWR ┆ 40.7 ┆ -74.17 ┆ 4.0 ┆ 19730… │
│ 725025-14734 ┆ NEWARK LIBERTY INTERNATIONAL ┆ US ┆ NJ ┆ KEWR ┆ 40.7 ┆ -74.17 ┆ 4.0 ┆ 19510… │
│ 725030-14732 ┆ LA GUARDIA AIRPORT ┆ US ┆ NY ┆ KLGA ┆ 40.78 ┆ -73.88 ┆ 3.0 ┆ 19730… │
│ 725033-14732 ┆ LA GUARDIA AIRPORT ┆ US ┆ NY ┆ KLGA ┆ 40.78 ┆ -73.88 ┆ 3.0 ┆ 19380… │
│ 725037-94728 ┆ JOHN F KENNEDY INTL AP ┆ US ┆ NY ┆ KJFK ┆ 40.64 ┆ -73.78 ┆ 3.4 ┆ 19730… │
│ 744860-94728 ┆ JOHN F KENNEDY INTL AP ┆ US ┆ NY ┆ KJFK ┆ 40.64 ┆ -73.78 ┆ 3.4 ┆ 19491… │
│ 999999-14732 ┆ NEW YORK/LA GUARDIA ┆ US ┆ NY ┆ null ┆ 40.78 ┆ -73.88 ┆ 3.4 ┆ 19310… │
│ 999999-94728 ┆ NEW YORK/JFK ┆ US ┆ NY ┆ null ┆ 40.64 ┆ -73.78 ┆ 3.4 ┆ 19310… │
└──────────────┴───────────────────────────────┴─────────┴───────┴───────┴───────┴─────────┴───────┴────────┘
Search by Name or Country
# Search by station name
airports = wv.search_stations(name="tokyo international")
airports
Output:
shape: (2, 9)
┌──────────────┬─────────────────────────────┬─────────┬───────┬───────┬───────┬────────┬───────┬────────┐
│ id ┆ name ┆ country ┆ state ┆ icao ┆ lat ┆ lon ┆ elev ┆ begin │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═════════════════════════════╪═════════╪═══════╪═══════╪═══════╪════════╪═══════╪════════╡
│ 476710-99999 ┆ TOKYO INTERNATIONAL AIRPORT ┆ JAPAN ┆ null ┆ RJTT ┆ 35.55 ┆ 139.78 ┆ 4.0 ┆ 19730… │
│ 476770-99999 ┆ TOKYO INTERNATIONAL AIRPORT ┆ JAPAN ┆ null ┆ RJTT ┆ 35.55 ┆ 139.78 ┆ 4.0 ┆ 19530… │
└──────────────┴─────────────────────────────┴─────────┴───────┴───────┴───────┴────────┴───────┴────────┘
# Search by country name
uk_stations = wv.search_stations(country="United Kingdom")
uk_stations.head()
Output:
shape: (5, 9)
┌──────────────┬──────────────────────┬────────────────┬───────┬───────┬───────┬────────┬───────┬────────┐
│ id ┆ name ┆ country ┆ state ┆ icao ┆ lat ┆ lon ┆ elev ┆ begin │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪══════════════════════╪════════════════╪═══════╪═══════╪═══════╪════════╪═══════╪════════╡
│ 030050-99999 ┆ LERWICK ┆ UNITED KINGDOM ┆ null ┆ ENSL ┆ 60.13 ┆ -1.18 ┆ 82.0 ┆ 19310… │
│ 030350-99999 ┆ KIRKWALL AIRPORT ┆ UNITED KINGDOM ┆ null ┆ EGPA ┆ 58.95 ┆ -2.9 ┆ 26.0 ┆ 19730… │
│ 030510-99999 ┆ STORNOWAY ┆ UNITED KINGDOM ┆ null ┆ EGPO ┆ 58.22 ┆ -6.32 ┆ 9.0 ┆ 19730… │
│ 030600-99999 ┆ CAPE WRATH ┆ UNITED KINGDOM ┆ null ┆ null ┆ 58.63 ┆ -5.0 ┆ 122.0 ┆ 19310… │
│ 030630-99999 ┆ WICK ┆ UNITED KINGDOM ┆ null ┆ EGPC ┆ 58.45 ┆ -3.08 ┆ 36.0 ┆ 19730… │
└──────────────┴──────────────────────┴────────────────┴───────┴───────┴───────┴────────┴───────┴────────┘
Get All Station Metadata
# Get metadata for all 29,000+ stations
all_stations = wv.get_station_metadata()
all_stations.head()
Output:
shape: (5, 9)
┌──────────────┬───────────────────────────┬─────────┬───────┬───────┬────────┬─────────┬────────┬────────┐
│ id ┆ name ┆ country ┆ state ┆ icao ┆ lat ┆ lon ┆ elev ┆ begin │
│ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ str ┆ str ┆ str ┆ str ┆ f64 ┆ f64 ┆ f64 ┆ str │
╞══════════════╪═══════════════════════════╪═════════╪═══════╪═══════╪════════╪═════════╪════════╪════════╡
│ 007005-99999 ┆ CWOS 07005 ┆ null ┆ null ┆ null ┆ null ┆ null ┆ null ┆ 19710… │
│ 007011-99999 ┆ CWOS 07011 ┆ null ┆ null ┆ null ┆ null ┆ null ┆ null ┆ 19730… │
│ 007018-99999 ┆ WXPOD 7018 ┆ null ┆ null ┆ null ┆ 0.0 ┆ 0.0 ┆ 7018.0 ┆ 20110… │
│ 007026-99999 ┆ WXPOD 7026 ┆ null ┆ null ┆ null ┆ 0.0 ┆ 0.0 ┆ 7026.0 ┆ 20050… │
│ 007070-99999 ┆ WXPOD 7070 ┆ null ┆ null ┆ null ┆ 0.0 ┆ 0.0 ┆ 7070.0 ┆ 20050… │
└──────────────┴───────────────────────────┴─────────┴───────┴───────┴────────┴─────────┴────────┴────────┘
Weather Data Columns
The returned DataFrame includes:
| Column | Description |
|---|---|
id |
Station identifier (USAF-WBAN format) |
time |
Observation time (local time by default) |
temp |
Air temperature (°C) |
dew_point |
Dew point temperature |
rh |
Relative humidity (%) |
wd |
Wind direction (degrees, 0-360) |
ws |
Wind speed (m/s) |
atmos_pres |
Sea level pressure (hPa) |
ceil_hgt |
Ceiling height (m, 22000 = unlimited) |
visibility |
Visibility (m, max 16000 = 10 miles) |
Advanced Usage
Include Station Metadata
Add station information (name, country, state, ICAO, coordinates, elevation) to each observation:
weather = wv.get_weather_data(
"725030-14732",
years=2024,
incl_stn_info=True
)
weather[["time", "temp", "name", "country"]].head()
Output:
shape: (5, 4)
┌─────────────────────────┬───────┬────────────────────┬─────────┐
│ time ┆ temp ┆ name ┆ country │
│ --- ┆ --- ┆ --- ┆ --- │
│ datetime[μs, tz] ┆ f64 ┆ str ┆ str │
╞═════════════════════════╪═══════╪════════════════════╪═════════╡
│ 2024-01-01 00:51:00 EST ┆ 12.8 ┆ LA GUARDIA AIRPORT ┆ US │
│ 2024-01-01 01:51:00 EST ┆ 12.2 ┆ LA GUARDIA AIRPORT ┆ US │
│ 2024-01-01 02:51:00 EST ┆ 11.7 ┆ LA GUARDIA AIRPORT ┆ US │
│ 2024-01-01 03:51:00 EST ┆ 11.1 ┆ LA GUARDIA AIRPORT ┆ US │
│ 2024-01-01 04:51:00 EST ┆ 10.6 ┆ LA GUARDIA AIRPORT ┆ US │
└─────────────────────────┴───────┴────────────────────┴─────────┘
Temperature Units
# Get temperatures in Fahrenheit
weather = wv.get_weather_data("725030-14732", years=2024, temp_unit="f")
weather[["time", "temp", "dew_point"]].head()
Output:
shape: (5, 3)
┌─────────────────────────┬───────┬───────────┐
│ time ┆ temp ┆ dew_point │
│ --- ┆ --- ┆ --- │
│ datetime[μs, tz] ┆ f64 ┆ f64 │
╞═════════════════════════╪═══════╪═══════════╡
│ 2024-01-01 00:51:00 EST ┆ 55.0 ┆ 46.0 │
│ 2024-01-01 01:51:00 EST ┆ 54.0 ┆ 45.0 │
│ 2024-01-01 02:51:00 EST ┆ 53.1 ┆ 44.6 │
│ 2024-01-01 03:51:00 EST ┆ 52.0 ┆ 43.9 │
│ 2024-01-01 04:51:00 EST ┆ 51.1 ┆ 43.3 │
└─────────────────────────┴───────┴───────────┘
Supported values: "c"/"celsius", "f"/"fahrenheit", "k"/"kelvin".
Multiple Years
# Get multiple years of data
weather = wv.get_weather_data(
"725030-14732",
years=[2022, 2023, 2024]
)
weather[["time", "temp"]].head()
Output:
shape: (5, 2)
┌─────────────────────────┬───────┐
│ time ┆ temp │
│ --- ┆ --- │
│ datetime[μs, tz] ┆ f64 │
╞═════════════════════════╪═══════╡
│ 2022-01-01 00:51:00 EST ┆ 2.2 │
│ 2022-01-01 01:51:00 EST ┆ 1.7 │
│ 2022-01-01 02:51:00 EST ┆ 1.1 │
│ 2022-01-01 03:51:00 EST ┆ 0.6 │
│ 2022-01-01 04:51:00 EST ┆ 0.0 │
└─────────────────────────┴───────┘
Hourly Resampling
# Resample to regular hourly intervals (fills missing hours with None)
weather = wv.get_weather_data(
"725030-14732",
years=2024,
make_hourly=True
)
weather[["time", "temp", "ws"]].head(10)
Output:
shape: (10, 3)
┌─────────────────────────┬───────┬──────┐
│ time ┆ temp ┆ ws │
│ --- ┆ --- ┆ --- │
│ datetime[μs, tz] ┆ f64 ┆ f64 │
╞═════════════════════════╪═══════╪══════╡
│ 2024-01-01 00:00:00 EST ┆ null ┆ null │
│ 2024-01-01 01:00:00 EST ┆ 12.8 ┆ 4.6 │
│ 2024-01-01 02:00:00 EST ┆ 12.2 ┆ 5.1 │
│ 2024-01-01 03:00:00 EST ┆ 11.7 ┆ 4.6 │
│ 2024-01-01 04:00:00 EST ┆ 11.1 ┆ 3.6 │
│ 2024-01-01 05:00:00 EST ┆ 10.6 ┆ 3.6 │
│ 2024-01-01 06:00:00 EST ┆ 10.0 ┆ 2.6 │
│ 2024-01-01 07:00:00 EST ┆ 10.0 ┆ 3.6 │
│ 2024-01-01 08:00:00 EST ┆ 10.0 ┆ 4.1 │
│ 2024-01-01 09:00:00 EST ┆ 10.6 ┆ 4.1 │
└─────────────────────────┴───────┴──────┘
Keep UTC Time
# Don't convert to local time (keep UTC time)
weather = wv.get_weather_data(
"725030-14732",
years=2024,
convert_to_local=False
)
weather[["time", "temp"]].head()
Output:
shape: (5, 2)
┌─────────────────────────┬───────┐
│ time ┆ temp │
│ --- ┆ --- │
│ datetime[μs, UTC] ┆ f64 │
╞═════════════════════════╪═══════╡
│ 2024-01-01 05:51:00 UTC ┆ 12.8 │
│ 2024-01-01 06:51:00 UTC ┆ 12.2 │
│ 2024-01-01 07:51:00 UTC ┆ 11.7 │
│ 2024-01-01 08:51:00 UTC ┆ 11.1 │
│ 2024-01-01 09:51:00 UTC ┆ 10.6 │
└─────────────────────────┴───────┘
Smart Data Caching
Cache downloaded files for offline use or faster repeated access:
# Cache in current directory
weather = wv.get_weather_data(
"725030-14732",
years=2024,
cache_dir="."
)
weather[["time", "temp"]].head()
Output:
shape: (5, 2)
┌─────────────────────────┬───────┐
│ time ┆ temp │
│ --- ┆ --- │
│ datetime[μs, tz] ┆ f64 │
╞═════════════════════════╪═══════╡
│ 2024-01-01 00:51:00 EST ┆ 12.8 │
│ 2024-01-01 01:51:00 EST ┆ 12.2 │
│ 2024-01-01 02:51:00 EST ┆ 11.7 │
│ 2024-01-01 03:51:00 EST ┆ 11.1 │
│ 2024-01-01 04:51:00 EST ┆ 10.6 │
└─────────────────────────┴───────┘
Weathervault automatically checks:
- Specified
cache_dir=(if provided) - Current working directory (for existing cached files)
and if no relevant data files are found, they are downloaded from NOAA.
Data Inventory
Check what data is available:
# Get the data inventory (record counts by station/year/month)
inventory = wv.get_inventory()
inventory.head()
Output:
shape: (5, 4)
┌──────────────┬──────┬───────┬────────┐
│ id ┆ year ┆ month ┆ count │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i32 ┆ i32 ┆ i32 │
╞══════════════╪══════╪═══════╪════════╡
│ 007005-99999 ┆ 1971 ┆ 5 ┆ 360 │
│ 007005-99999 ┆ 1971 ┆ 6 ┆ 356 │
│ 007005-99999 ┆ 1971 ┆ 7 ┆ 364 │
│ 007005-99999 ┆ 1971 ┆ 8 ┆ 363 │
│ 007005-99999 ┆ 1971 ┆ 9 ┆ 361 │
└──────────────┴──────┴───────┴────────┘
# Filter to a specific station
import polars as pl
station_inv = inventory.filter(pl.col("id") == "725030-14732")
station_inv.head()
Output:
shape: (5, 4)
┌──────────────┬──────┬───────┬───────┐
│ id ┆ year ┆ month ┆ count │
│ --- ┆ --- ┆ --- ┆ --- │
│ str ┆ i32 ┆ i32 ┆ i32 │
╞══════════════╪══════╪═══════╪═══════╡
│ 725030-14732 ┆ 1973 ┆ 1 ┆ 744 │
│ 725030-14732 ┆ 1973 ┆ 2 ┆ 672 │
│ 725030-14732 ┆ 1973 ┆ 3 ┆ 744 │
│ 725030-14732 ┆ 1973 ┆ 4 ┆ 720 │
│ 725030-14732 ┆ 1973 ┆ 5 ┆ 744 │
└──────────────┴──────┴───────┴───────┘
License
MIT License. See LICENSE for details.
Metadata
Release files for weathervault 0.2.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | Actions |
|---|---|---|---|---|
| weathervault-0.2.0.tar.gz | 56.5 kB | Without provenance | Details for weathervault-0.2.0.tar.gz |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Actions Reset |
|---|---|---|---|---|
| weathervault-0.2.0-py3-none-any.whl | Python 3 | none | any | Details for weathervault-0.2.0-py3-none-any.whl |
Total release size: 88.6 kB
Release files / weathervault-0.2.0.tar.gz
| Download URL | weathervault-0.2.0.tar.gz |
|---|---|
| Size | 56.5 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
04fef21e34902e6bf4a105f99753f9e8b335fec95e9f711c4ec8495f5e3799b8
|
|
BLAKE2b-256 checksum How to use checksums |
28ca6e06ee426b18af95d8098af18cecda4a20f863f968a12e3c795e3e1262bf
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Release files / weathervault-0.2.0-py3-none-any.whl
| Download URL | weathervault-0.2.0-py3-none-any.whl |
|---|---|
| Size | 32.1 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
c37e56adb5020d077f63025063f725ff97484e37839dd679c206796ad7a2bdc6
|
|
BLAKE2b-256 checksum How to use checksums |
bc0b23b1df8b563012a086921d5dcca8d157405835727c2e5874520303854a99
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.13.7
|
Security for weathervault 0.2.0
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.
To learn more about protecting yourself from malicious actors, visit our package security documentation.