Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/docs-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ jobs:
fail-fast: false
matrix:
include:
- python-version: '3.10'
- python-version: 3.11
os: Windows
- python-version: 3.11
os: macOS
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/docs.yml
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.10', 3.11, 3.12]
python-version: [3.11, 3.12]
check-links: [false]
include:
- python-version: 3.13
Expand Down
4 changes: 1 addition & 3 deletions .github/workflows/tests-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,11 +28,9 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.10', 3.13]
python-version: [3.11, 3.13]
os: [macOS, Windows]
include:
- python-version: 3.11
os: Windows
- python-version: 3.12
os: macOS

Expand Down
6 changes: 3 additions & 3 deletions .github/workflows/tests-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,13 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: ['3.10', 3.11, 3.12, 3.13]
python-version: [3.11, 3.12, 3.13]
dep-versions: [Latest]
no-extras: ['']
include:
- python-version: '3.10'
- python-version: '3.11'
dep-versions: Minimum
- python-version: '3.10'
- python-version: '3.11'
dep-versions: Minimum
no-extras: 'No Extras'
- python-version: 3.13
Expand Down
2 changes: 1 addition & 1 deletion .python-version
Original file line number Diff line number Diff line change
@@ -1 +1 @@
3.10
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

With a dependabot bug fixed, this whole file can be deleted now.

3.11
5 changes: 3 additions & 2 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,8 +232,9 @@ MetPy documentation via the `gh-pages` branch on GitHub.

Unit tests are the lifeblood of the project, as it ensures that we can continue to add and
change the code and stay confident that things have not broken. Running the tests requires
``pytest``, which is easily available through ``conda`` or ``pip``. It was also installed if
you made our default ``devel`` environment.
``pytest``, which is easily available through ``conda``, ``pip``, or after installing the
`test` extras with `uv`. It was also installed if you made our default ``devel``
environment.

### Running Tests

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ on a future ``1.x`` version.
For additional MetPy examples not included in this repository, please see the
[MetPy Cookbook on Project Pythia](https://projectpythia.org/metpy-cookbook/index.html).

We support Python >= 3.10.
We support Python >= 3.11.

Need Help?
----------
Expand Down
2 changes: 1 addition & 1 deletion docs/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ MetPy
=====

MetPy is a collection of tools in Python for reading, visualizing, and performing calculations
with weather data. MetPy supports Python >= 3.10 and is freely available under a permissive
with weather data. MetPy supports Python >= 3.11 and is freely available under a permissive
`open source license <https://github.com/Unidata/MetPy/blob/main/LICENSE>`_.

If you're new to MetPy, check out our :doc:`Getting Started <userguide/startingguide>` guide.
Expand Down
2 changes: 1 addition & 1 deletion docs/userguide/installguide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ Requirements
------------
In general, MetPy tries to support minor versions of dependencies released within the last two
years. For Python itself, that generally means supporting the last two minor releases; MetPy
currently supports Python >= 3.10.
currently supports Python >= 3.11.

.. literalinclude:: ../../pyproject.toml
:start-at: matplotlib
Expand Down
2 changes: 1 addition & 1 deletion examples/meteogram_metpy.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ def __init__(self, fig, dates, probeid, time=None, axis=0):
axis: number that controls the new axis to be plotted (FOR FUTURE)
"""
if not time:
time = dt.datetime.now(dt.timezone.utc)
time = dt.datetime.now(dt.UTC)
self.start = dates[0]
self.fig = fig
self.end = dates[-1]
Expand Down
3 changes: 1 addition & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,6 @@ classifiers = [
"Development Status :: 5 - Production/Stable",
"Framework :: Matplotlib",
"Programming Language :: Python",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Programming Language :: Python :: 3.13",
Expand All @@ -24,7 +23,7 @@ classifiers = [
"Operating System :: OS Independent",
"License :: OSI Approved :: BSD License"
]
requires-python = ">=3.10"
requires-python = ">=3.11"
dependencies = [
"matplotlib>=3.5.0",
"numpy>=1.23.0",
Expand Down
4 changes: 2 additions & 2 deletions src/metpy/io/metar.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
# Import the necessary libraries
from collections import namedtuple
import contextlib
from datetime import datetime, timezone
from datetime import datetime, UTC
import warnings

import numpy as np
Expand Down Expand Up @@ -433,7 +433,7 @@ def _metars_to_dataframe(metar_iter, *, year=None, month=None):

# Defaults year and/or month to present reported date if not provided
if year is None or month is None:
now = datetime.now(timezone.utc)
now = datetime.now(UTC)
year = now.year if year is None else year
month = now.month if month is None else month

Expand Down
4 changes: 2 additions & 2 deletions src/metpy/io/nexrad.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
import bz2
from collections import defaultdict, namedtuple, OrderedDict
import contextlib
from datetime import datetime, timezone
from datetime import datetime, UTC
import logging
import pathlib
import re
Expand Down Expand Up @@ -76,7 +76,7 @@ def nexrad_to_datetime(julian_date, ms_midnight):
"""Convert NEXRAD date time format to python `datetime.datetime`."""
# Subtracting one from julian_date is because epoch date is 1
return datetime.fromtimestamp((julian_date - 1) * day + ms_midnight * milli,
tz=timezone.utc).replace(tzinfo=None)
tz=UTC).replace(tzinfo=None)


def remap_status(val):
Expand Down
4 changes: 2 additions & 2 deletions src/metpy/io/text.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
"""Support reading information from various text file formats."""

import contextlib
from datetime import datetime, timezone
from datetime import datetime, UTC
import re
import string

Expand Down Expand Up @@ -102,7 +102,7 @@ def parse_wpc_surface_bulletin(bulletin, year=None):
text = file.read().decode('utf-8')

parsed_text = []
valid_time = datetime.now(timezone.utc).replace(tzinfo=None)
valid_time = datetime.now(UTC).replace(tzinfo=None)
for parts in _regroup_lines(text.splitlines()):
# A single file may have multiple sets of data that are valid at different times. Set
# the valid_time string that will correspond to all the following lines parsed, until
Expand Down
4 changes: 2 additions & 2 deletions src/metpy/plots/_util.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
"""Utilities for use in making plots."""

from datetime import datetime, timezone
from datetime import datetime, UTC

from matplotlib.collections import LineCollection
import matplotlib.patheffects as mpatheffects
Expand Down Expand Up @@ -52,7 +52,7 @@ def add_timestamp(ax, time=None, x=0.99, y=-0.04, ha='right', high_contrast=Fals
text_args = {}
text_args.update(**kwargs)
if not time:
time = datetime.now(timezone.utc)
time = datetime.now(UTC)
timestr = time.strftime(time_format)
# If we don't have a time string after that, assume xarray/numpy and see if item
if not isinstance(timestr, str):
Expand Down
10 changes: 3 additions & 7 deletions src/metpy/plots/station_plot.py
Original file line number Diff line number Diff line change
Expand Up @@ -371,13 +371,9 @@ def _make_kwargs(self, kwargs):
def _to_string_list(vals, fmt):
"""Convert a sequence of values to a list of strings."""
if fmt is None:
import sys
if sys.version_info >= (3, 11):
fmt = 'z.0f'
else:
def fmt(s):
"""Perform default formatting with no decimal places and no negative 0."""
return format(round(s, 0) + 0., '.0f')
def fmt(s):
"""Perform default formatting with no decimal places and no negative 0."""
return format(round(s, 0) + 0., '.0f')
Comment on lines +374 to +376
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, instead the format string should have been kept (apparently this got swallowed when I reviewed earlier):

Suggested change
def fmt(s):
"""Perform default formatting with no decimal places and no negative 0."""
return format(round(s, 0) + 0., '.0f')
fmt = 'z.0f'

if not callable(fmt):
def formatter(s):
"""Turn a format string into a callable."""
Expand Down
22 changes: 11 additions & 11 deletions src/metpy/remote/aws.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
# SPDX-License-Identifier: BSD-3-Clause
"""Tools for reading known collections of data that are hosted on Amazon Web Services (AWS)."""
import bisect
from datetime import datetime, timedelta, timezone
from datetime import datetime, timedelta, UTC
import itertools
from pathlib import Path
import shutil
Expand All @@ -18,7 +18,7 @@

def ensure_timezone(dt):
"""Add UTC timezone if no timezone present."""
return dt.replace(tzinfo=timezone.utc) if dt.tzinfo is None else dt
return dt.replace(tzinfo=UTC) if dt.tzinfo is None else dt


class AWSProduct:
Expand Down Expand Up @@ -239,7 +239,7 @@ def _build_key(self, site, prod_id, dt, depth=None):
def dt_from_key(self, key): # noqa: D102
# Docstring inherited
return datetime.strptime(key.split(self.delimiter, maxsplit=2)[-1],
'%Y_%m_%d_%H_%M_%S').replace(tzinfo=timezone.utc)
'%Y_%m_%d_%H_%M_%S').replace(tzinfo=UTC)

def get_range(self, site, prod_id, start, end):
"""Yield products within a particular date/time range.
Expand Down Expand Up @@ -317,7 +317,7 @@ def get_product(self, site, prod_id, dt=None):
product_ids, sites, get_range

"""
dt = datetime.now(timezone.utc) if dt is None else ensure_timezone(dt)
dt = datetime.now(UTC) if dt is None else ensure_timezone(dt)

# We work with a list of keys/prefixes that we iteratively find that bound our target
# key. To start, this only contains the site and product.
Expand Down Expand Up @@ -389,7 +389,7 @@ def sites(self, dt=None):

"""
if dt is None:
dt = datetime.now(timezone.utc)
dt = datetime.now(UTC)
prefix = self._build_key('', dt, depth=3) + self.delimiter
return [item.split('/')[-2] for item in self.common_prefixes(prefix)]

Expand All @@ -401,7 +401,7 @@ def _build_key(self, site, dt, depth=None):
def dt_from_key(self, key): # noqa: D102
# Docstring inherited
return datetime.strptime(key.rsplit(self.delimiter, maxsplit=1)[-1][4:19],
'%Y%m%d_%H%M%S').replace(tzinfo=timezone.utc)
'%Y%m%d_%H%M%S').replace(tzinfo=UTC)

def get_range(self, site, start, end):
"""Yield products within a particular date/time range.
Expand Down Expand Up @@ -450,7 +450,7 @@ def get_product(self, site, dt=None):
sites, get_range

"""
dt = datetime.now(timezone.utc) if dt is None else ensure_timezone(dt)
dt = datetime.now(UTC) if dt is None else ensure_timezone(dt)
search_key = self._build_key(site, dt)
prefix = search_key.split('_')[0]
objs = (self.objects(prefix) if self.include_mdm else
Expand Down Expand Up @@ -530,7 +530,7 @@ def _subprod_prefix(self, prefix, mode, band):
def dt_from_key(self, key): # noqa: D102
# Docstring inherited
start_time = key.split('_')[-3]
return datetime.strptime(start_time[:-1], 's%Y%j%H%M%S').replace(tzinfo=timezone.utc)
return datetime.strptime(start_time[:-1], 's%Y%j%H%M%S').replace(tzinfo=UTC)

def get_product(self, product, dt=None, mode=None, band=None):
"""Get a product from the archive.
Expand All @@ -556,7 +556,7 @@ def get_product(self, product, dt=None, mode=None, band=None):
product_ids, get_range

"""
dt = datetime.now(timezone.utc) if dt is None else ensure_timezone(dt)
dt = datetime.now(UTC) if dt is None else ensure_timezone(dt)
time_prefix = self._build_time_prefix(product, dt)
prod_prefix = self._subprod_prefix(time_prefix, mode, band)
return self._closest_result(self.objects(prod_prefix), dt)
Expand Down Expand Up @@ -645,7 +645,7 @@ def dt_from_key(self, key): # noqa: D102
# Docstring inherited
# GRAP_v100_GFS_2025021212_f000_f240_06.nc
dt = key.split('/')[-1].split('_')[3]
return datetime.strptime(dt, '%Y%m%d%H').replace(tzinfo=timezone.utc)
return datetime.strptime(dt, '%Y%m%d%H').replace(tzinfo=UTC)

def get_product(self, model, dt=None, version=None, init=None):
"""Get a product from the archive.
Expand Down Expand Up @@ -673,7 +673,7 @@ def get_product(self, model, dt=None, version=None, init=None):
get_range

"""
dt = datetime.now(timezone.utc) if dt is None else ensure_timezone(dt)
dt = datetime.now(UTC) if dt is None else ensure_timezone(dt)
model_id = self._model_id(model, version, init)
search_key = self._build_key(model_id, dt)
prefix = search_key.rsplit('_', maxsplit=4)[0]
Expand Down
Loading