Skip to content

Commit

Permalink
Merge pull request #1841 from dopplershift/drop36
Browse files Browse the repository at this point in the history
Drop support for Python 3.6
  • Loading branch information
dcamron committed May 3, 2021
2 parents 879fdf7 + 3150eb9 commit fee4d78
Show file tree
Hide file tree
Showing 28 changed files with 97 additions and 136 deletions.
9 changes: 2 additions & 7 deletions .github/workflows/docs-conda.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ on:

jobs:
#
# Build our docs on macOS and Windows on Python 3.6 and 3.7, respectively.
# Build our docs on macOS and Windows on Python 3.8 and 3.7, respectively.
#
Docs:
name: ${{ matrix.os }} ${{ matrix.python-version }}
Expand All @@ -19,7 +19,7 @@ jobs:
fail-fast: false
matrix:
include:
- python-version: 3.6
- python-version: 3.8
os: macOS
- python-version: 3.7
os: Windows
Expand Down Expand Up @@ -55,11 +55,6 @@ jobs:
# Needed for caching
use-only-tar-bz2: true

# TODO: Remove this when we drop Python 3.6
- name: Adjust traitlets dependency for Python 3.6
if: ${{ matrix.python-version == 3.6 }}
run: sed -e "s/traitlets==.*/traitlets==4.3.3/" -i.bak ci/requirements.txt

# TODO: Remove this when scipy>1.5.3 is available on conda-forge
- name: Adjust scipy dependency for Conda
run: sed -e "s/scipy==.*/scipy==1.5.3/" -i.bak ci/requirements.txt
Expand Down
9 changes: 2 additions & 7 deletions .github/workflows/tests-pypi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,11 @@ jobs:
strategy:
fail-fast: false
matrix:
python-version: [3.6, 3.7, 3.8, 3.9]
python-version: [3.7, 3.8, 3.9]
dep-versions: [requirements.txt]
no-extras: ['']
include:
- python-version: 3.6
- python-version: 3.7
dep-versions: Minimum
no-extras: ''
- python-version: 3.9
Expand Down Expand Up @@ -63,11 +63,6 @@ jobs:
pip-tests-${{ runner.os }}-
pip-tests-
# TODO: Remove this when we drop Python 3.6
- name: Adjust traitlets dependency for Python 3.6
if: ${{ matrix.python-version == 3.6 }}
run: sed -e "s/traitlets==.*/traitlets==4.3.3/" -i.bak ci/requirements.txt

- name: Add extras to requirements
if: ${{ matrix.no-extras != 'No Extras' }}
run: cat ci/extra_requirements.txt >> ci/test_requirements.txt
Expand Down
6 changes: 1 addition & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,11 +30,7 @@ on a future ``1.x`` version.
For additional MetPy examples not included in this repository, please see the [Unidata Python
Gallery](https://unidata.github.io/python-gallery/).

We support Python >= 3.6.

0.12 is the first version to drop support for Python 2.7 in Fall 2019. See
[here](https://github.com/Unidata/MetPy/blob/main/docs/installguide.rst) for more
information.
We support Python >= 3.7.

Need Help?
----------
Expand Down
4 changes: 2 additions & 2 deletions ci/Minimum
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
importlib_metadata==1.0.0
importlib_resources==1.3.0
matplotlib==2.1.0
matplotlib==3.0.1
numpy==1.16.0
pandas==0.24.0
pint==0.10.1
pooch==0.1
pyproj==2.3.0
scipy==1.0.0
scipy==1.2.0
traitlets==4.3.0
xarray==0.14.1
18 changes: 10 additions & 8 deletions docs/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

from datetime import datetime
import os
from pathlib import Path
import re
import sys

Expand All @@ -19,9 +20,10 @@

# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
sys.path.insert(0, os.path.abspath('.'))
sys.path.insert(0, os.path.abspath(os.path.join('..', '..')))
# documentation root, use resolve() to make it absolute, like shown here.
cwd = Path.cwd().resolve()
sys.path.insert(0, str(cwd))
sys.path.insert(0, str(cwd.parent.parent))

# -- General configuration ------------------------------------------------

Expand Down Expand Up @@ -49,11 +51,11 @@
'reference_url': {
'metpy': None,
},
'examples_dirs': [os.path.join('..', 'examples'), os.path.join('..', 'tutorials')],
'examples_dirs': [str(cwd.parent / 'examples'), str(cwd.parent / 'tutorials')],
'gallery_dirs': ['examples', 'tutorials'],
'filename_pattern': r'\.py',
'backreferences_dir': os.path.join('api', 'generated'),
'default_thumb_file': os.path.join('_static', 'metpy_150x150_white_bg.png'),
'backreferences_dir': str(Path('api') / 'generated'),
'default_thumb_file': str(Path('_static') / 'metpy_150x150_white_bg.png'),
'abort_on_example_error': True
}

Expand Down Expand Up @@ -208,12 +210,12 @@

# The name of an image file (relative to this directory) to place at the top
# of the sidebar.
html_logo = os.path.join('_static', 'metpy_horizontal.png')
html_logo = str(Path('_static') / 'metpy_horizontal.png')

# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = os.path.join('_static', 'metpy_32x32.ico')
html_favicon = str(Path('_static') / 'metpy_32x32.ico')

# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
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.6 and is freely available under a permissive
with weather data. MetPy supports Python >= 3.7 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
11 changes: 4 additions & 7 deletions docs/override_check.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,21 +4,18 @@
#
# Verifies that any modules present in the _templates/overrides directory have all of their
# their exported functions included in the doc file.
import glob
import importlib
import os
from pathlib import Path
import sys


modules_to_skip = ['metpy.xarray']


failed = False
for full_path in glob.glob('_templates/overrides/metpy.*.rst'):

filename = os.path.basename(full_path)
module = filename.split('.rst')[0]
for full_path in (Path('_templates') / 'overrides').glob('metpy.*.rst'):

module = full_path.with_suffix('').name
if module in modules_to_skip:
continue

Expand All @@ -37,7 +34,7 @@
if missing_functions:
failed = True
print('ERROR - The following functions are missing from the override file ' +
filename + ': ' + ', '.join(missing_functions), file=sys.stderr)
str(full_path.name) + ': ' + ', '.join(missing_functions), file=sys.stderr)

# Report status
if failed:
Expand Down
6 changes: 3 additions & 3 deletions docs/userguide/installguide.rst
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,15 @@ 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.6.
currently supports Python >= 3.7.

* matplotlib >= 2.1.0
* matplotlib >= 3.0.1
* numpy >= 1.16.0
* pandas >= 0.24.0
* pint >= 0.10.1
* pooch >= 0.1
* pyproj >= 2.3.0
* scipy >= 1.0.0
* scipy >= 1.2.0
* traitlets >= 4.3.0
* xarray >= 0.14.1

Expand Down
9 changes: 4 additions & 5 deletions examples/cross_section.py
Original file line number Diff line number Diff line change
Expand Up @@ -120,11 +120,10 @@

# Set the titles and axes labels
ax_inset.set_title('')
ax.set_title('NARR Cross-Section \u2013 {} to {} \u2013 Valid: {}\n'
'Potential Temperature (K), Tangential/Normal Winds (knots), '
'Relative Humidity (dimensionless)\n'
'Inset: Cross-Section Path and 500 hPa Geopotential Height'.format(
start, end, cross['time'].dt.strftime('%Y-%m-%d %H:%MZ').item()))
ax.set_title(f'NARR Cross-Section \u2013 {start} to {end} \u2013 '
f'Valid: {cross["time"].dt.strftime("%Y-%m-%d %H:%MZ").item()}\n'
'Potential Temperature (K), Tangential/Normal Winds (knots), Relative Humidity '
'(dimensionless)\nInset: Cross-Section Path and 500 hPa Geopotential Height')
ax.set_ylabel('Pressure (hPa)')
ax.set_xlabel('Longitude (degrees east)')
rh_colorbar.set_label('Relative Humidity (dimensionless)')
Expand Down
6 changes: 2 additions & 4 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ classifiers =
Development Status :: 5 - Production/Stable
Framework :: Matplotlib
Programming Language :: Python
Programming Language :: Python :: 3.6
Programming Language :: Python :: 3.7
Programming Language :: Python :: 3.8
Programming Language :: Python :: 3.9
Expand All @@ -38,7 +37,7 @@ package_dir =
packages = find:
include_package_data = True
setup_requires = setuptools_scm
python_requires = >=3.6
python_requires = >=3.7
install_requires =
importlib_metadata>=1.0.0; python_version < '3.8'
importlib_resources>=1.3.0; python_version < '3.9'
Expand Down Expand Up @@ -81,11 +80,10 @@ rst-roles = class, data, doc, func, meth, mod
rst-directives = plot, versionchanged
docstring-convention = numpy
exclude = docs build src/metpy/io/metar_parser.py
select = A B C D E F H I M Q RST S T W B902
select = A B C D E F G H I J K L M N O P Q R S T U V W X Y Z B902
ignore = F405 W503 RST902 SIM106
per-file-ignores = examples/*.py: D MPY001 T003 T001
tutorials/*.py: D MPY001 T003 T001
src/metpy/xarray.py: RST304
src/metpy/deprecation.py: C801
src/metpy/calc/*.py: RST306
src/metpy/interpolate/*.py: RST306
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@

if sys.version_info[0] < 3:
error = """
MetPy v0.12 and greater requires the Python 3.6 or above.
MetPy v1.1 and greater requires Python 3.7 or above.
If you're using Python 2.7, please install MetPy v0.11.1,
which is the last release of MetPy that supports Python 2.7,
but it is no longer maintained.
Expand Down
6 changes: 3 additions & 3 deletions src/metpy/calc/thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -3238,11 +3238,11 @@ def lifted_index(pressure, temperature, parcel_profile):
# find the index for the 500 hPa pressure level.
idx = np.where(pressure == units.Quantity(500, 'hPa'))
# find the measured temperature at 500 hPa.
T500 = temperature[idx]
t500 = temperature[idx]
# find the parcel profile temperature at 500 hPa.
Tp500 = parcel_profile[idx]
tp500 = parcel_profile[idx]
# calculate the lifted index.
lifted_index = T500 - Tp500.to(units.degC)
lifted_index = t500 - tp500.to(units.degC)
return lifted_index


Expand Down
4 changes: 2 additions & 2 deletions src/metpy/io/_tools.py
Original file line number Diff line number Diff line change
Expand Up @@ -264,7 +264,7 @@ def read_binary(self, num, item_type='B'):
else:
order = '@'

return list(self.read_struct(Struct(order + '{:d}'.format(int(num)) + item_type)))
return list(self.read_struct(Struct(order + f'{int(num):d}' + item_type)))

def read_int(self, size, endian, signed):
"""Parse the current buffer offset as the specified integer code."""
Expand Down Expand Up @@ -314,7 +314,7 @@ def __getitem__(self, item):

def __str__(self):
"""Return a string representation of the IOBuffer."""
return 'Size: {} Offset: {}'.format(len(self._data), self._offset)
return f'Size: {len(self._data)} Offset: {self._offset}'

def __len__(self):
"""Return the amount of data in the buffer."""
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 @@ -452,7 +452,7 @@ def _decode_msg5(self, msg_hdr):
def _decode_msg13(self, msg_hdr):
data = self._buffer_segment(msg_hdr)
if data:
data = Struct('>{:d}h'.format(len(data) // 2)).unpack(data)
data = Struct(f'>{len(data) // 2:d}h').unpack(data)
# Legacy format doesn't have date/time and has fewer azimuths
if data[0] <= 5:
num_el = data[0]
Expand Down Expand Up @@ -495,7 +495,7 @@ def _decode_msg15(self, msg_hdr):
# will be returned concatenated when this is the case
data = self._buffer_segment(msg_hdr)
if data:
date, time, num_el, *data = Struct('>{:d}h'.format(len(data) // 2)).unpack(data)
date, time, num_el, *data = Struct(f'>{len(data) // 2:d}h').unpack(data)
if num_el == 0:
log.info('Message 15 num_el is 0--likely legacy clutter filter notch width. '
'Skipping...')
Expand Down
19 changes: 9 additions & 10 deletions src/metpy/plots/ctables.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,8 @@ def plot_color_gradients(cmap_category, cmap_list, nrows):
"""

import ast
import glob
import logging
import os.path
from pathlib import Path

import matplotlib.colors as mcolors

Expand Down Expand Up @@ -112,7 +111,7 @@ def convert_gempak_table(infile, outfile):
for line in infile:
if not line.startswith('!') and line.strip():
r, g, b = map(int, line.split())
outfile.write('({:f}, {:f}, {:f})\n'.format(r / 255, g / 255, b / 255))
outfile.write(f'({r / 255:f}, {g / 255:f}, {b / 255:f})\n')


class ColortableRegistry(dict):
Expand Down Expand Up @@ -152,15 +151,15 @@ def scan_dir(self, path):
The path to the directory with the color tables
"""
for fname in glob.glob(os.path.join(path, '*' + TABLE_EXT)):
if os.path.isfile(fname):
with open(fname) as fobj:
for entry in Path(path).glob('*' + TABLE_EXT):
if entry.is_file():
with entry.open() as fobj:
try:
self.add_colortable(fobj, os.path.splitext(os.path.basename(fname))[0])
log.debug('Added colortable from file: %s', fname)
self.add_colortable(fobj, entry.with_suffix('').name)
log.debug('Added colortable from file: %s', entry)
except RuntimeError:
# If we get a file we can't handle, assume we weren't meant to.
log.info('Skipping unparsable file: %s', fname)
log.info('Skipping unparsable file: %s', entry)

def add_colortable(self, fobj, name):
r"""Add a color table from a file to the registry.
Expand Down Expand Up @@ -274,7 +273,7 @@ def get_colortable(self, name):

registry = ColortableRegistry()
registry.scan_resource('metpy.plots', 'colortable_files')
registry.scan_dir(os.path.curdir)
registry.scan_dir(Path.cwd())

with exporter:
colortables = registry
4 changes: 2 additions & 2 deletions tests/calc/test_indices.py
Original file line number Diff line number Diff line change
Expand Up @@ -76,11 +76,11 @@ def test_mean_pressure_weighted():
def test_mean_pressure_weighted_temperature():
"""Test pressure-weighted mean temperature function with vertical interpolation."""
data = get_upper_air_data(datetime(2016, 5, 22, 0), 'DDC')
T, = mean_pressure_weighted(data['pressure'],
t, = mean_pressure_weighted(data['pressure'],
data['temperature'],
height=data['height'],
depth=6000 * units('meter'))
assert_almost_equal(T, 281.535035296836 * units('kelvin'), 7)
assert_almost_equal(t, 281.535035296836 * units('kelvin'), 7)


def test_mean_pressure_weighted_elevated():
Expand Down
6 changes: 3 additions & 3 deletions tests/calc/test_thermo.py
Original file line number Diff line number Diff line change
Expand Up @@ -1830,7 +1830,7 @@ def test_cape_cin_value_error():
assert_almost_equal(cin, expected_cin, 3)


def test_lcl_grid_surface_LCLs():
def test_lcl_grid_surface_lcls():
"""Test surface grid where some values have LCLs at the surface."""
pressure = np.array([1000, 990, 1010]) * units.hPa
temperature = np.array([15, 14, 13]) * units.degC
Expand Down Expand Up @@ -1863,8 +1863,8 @@ def test_lifted_index():
-34.1, -37.3, -32.3, -34.1, -37.3, -41.1, -37.7, -58.1,
-57.5]) * units.degC
parcel_prof = parcel_profile(pressure, temperature[0], dewpoint[0])
LI = lifted_index(pressure, temperature, parcel_prof)
assert_almost_equal(LI, -7.9176350 * units.delta_degree_Celsius, 2)
li = lifted_index(pressure, temperature, parcel_prof)
assert_almost_equal(li, -7.9176350 * units.delta_degree_Celsius, 2)


def test_gradient_richardson_number():
Expand Down

0 comments on commit fee4d78

Please sign in to comment.