diff --git a/docs/override_check.py b/docs/override_check.py index 6469d4642c5..1b8fa125a87 100644 --- a/docs/override_check.py +++ b/docs/override_check.py @@ -4,9 +4,6 @@ # # Verifies that any modules present in the _templates/overrides directory have all of their # their exported functions included in the doc file. - -from __future__ import print_function - import glob import importlib import os diff --git a/examples/Four_Panel_Map.py b/examples/Four_Panel_Map.py index dfecde8de28..4bb7e1fbd4f 100644 --- a/examples/Four_Panel_Map.py +++ b/examples/Four_Panel_Map.py @@ -107,7 +107,7 @@ def plot_background(ax): transform=ccrs.PlateCarree(), zorder=0) axlist[2].set_title('Surface Temperatures', fontsize=16) cb3 = fig.colorbar(cf3, ax=axlist[2], orientation='horizontal', shrink=0.74, pad=0) -cb3.set_label(u'\N{DEGREE FAHRENHEIT}', size='x-large') +cb3.set_label('\N{DEGREE FAHRENHEIT}', size='x-large') # Lower right plot - precipitable water entire atmosphere cf4 = axlist[3].contourf(lon_2d, lat_2d, precip_water, cmap='Greens', diff --git a/examples/formats/NEXRAD_Level_3_File.py b/examples/formats/NEXRAD_Level_3_File.py index e1a68983b23..1f23c5a84f3 100644 --- a/examples/formats/NEXRAD_Level_3_File.py +++ b/examples/formats/NEXRAD_Level_3_File.py @@ -21,7 +21,7 @@ ('NWS8bitVel', -100, 1.0)) # m/s for v, ctable, ax in zip(('N0Q', 'N0U'), ctables, axes): # Open the file - name = get_test_data('nids/KOUN_SDUS54_{}TLX_201305202016'.format(v), as_file_obj=False) + name = get_test_data(f'nids/KOUN_SDUS54_{v}TLX_201305202016', as_file_obj=False) f = Level3File(name) # Pull the data out of the file object diff --git a/examples/gridding/Inverse_Distance_Verification.py b/examples/gridding/Inverse_Distance_Verification.py index dd98cf2abe2..6819cd973c0 100644 --- a/examples/gridding/Inverse_Distance_Verification.py +++ b/examples/gridding/Inverse_Distance_Verification.py @@ -101,8 +101,8 @@ def draw_circle(ax, x, y, r, m, label): draw_circle(ax, sim_gridx[0], sim_gridy[0], m='k-', r=radius, label='grid 0 radius') draw_circle(ax, sim_gridx[1], sim_gridy[1], m='b-', r=radius, label='grid 1 radius') -ax.annotate('grid 0: cressman {:.3f}'.format(cress_val), xy=(sim_gridx[0] + 2, sim_gridy[0])) -ax.annotate('grid 1: barnes {:.3f}'.format(barnes_val), xy=(sim_gridx[1] + 2, sim_gridy[1])) +ax.annotate(f'grid 0: cressman {cress_val:.3f}', xy=(sim_gridx[0] + 2, sim_gridy[0])) +ax.annotate(f'grid 1: barnes {barnes_val:.3f}', xy=(sim_gridx[1] + 2, sim_gridy[1])) ax.set_aspect('equal', 'datalim') ax.legend() @@ -114,8 +114,7 @@ def draw_circle(ax, x, y, r, m, label): # Plot the grid point, observations within radius of the grid point, their locations, and # their distances from the grid point. fig, ax = plt.subplots(1, 1, figsize=(15, 10)) -ax.annotate('grid 0: ({}, {})'.format(sim_gridx[0], sim_gridy[0]), - xy=(sim_gridx[0] + 2, sim_gridy[0])) +ax.annotate(f'grid 0: ({sim_gridx[0]}, {sim_gridy[0]})', xy=(sim_gridx[0] + 2, sim_gridy[0])) ax.plot(sim_gridx[0], sim_gridy[0], '+', markersize=10) mx, my = obs_tree.data[indices[0]].T @@ -128,8 +127,8 @@ def draw_circle(ax, x, y, r, m, label): xave = np.mean([sim_gridx[0], x]) yave = np.mean([sim_gridy[0], y]) - ax.annotate('distance: {}'.format(d), xy=(xave, yave)) - ax.annotate('({}, {}) : {} F'.format(x, y, z), xy=(x, y)) + ax.annotate(f'distance: {d}', xy=(xave, yave)) + ax.annotate(f'({x}, {y}) : {z} F', xy=(x, y)) ax.set_xlim(0, 80) ax.set_ylim(0, 80) @@ -154,8 +153,7 @@ def draw_circle(ax, x, y, r, m, label): # Now repeat for grid 1, except use barnes interpolation. fig, ax = plt.subplots(1, 1, figsize=(15, 10)) -ax.annotate('grid 1: ({}, {})'.format(sim_gridx[1], sim_gridy[1]), - xy=(sim_gridx[1] + 2, sim_gridy[1])) +ax.annotate(f'grid 1: ({sim_gridx[1]}, {sim_gridy[1]})', xy=(sim_gridx[1] + 2, sim_gridy[1])) ax.plot(sim_gridx[1], sim_gridy[1], '+', markersize=10) mx, my = obs_tree.data[indices[1]].T @@ -168,8 +166,8 @@ def draw_circle(ax, x, y, r, m, label): xave = np.mean([sim_gridx[1], x]) yave = np.mean([sim_gridy[1], y]) - ax.annotate('distance: {}'.format(d), xy=(xave, yave)) - ax.annotate('({}, {}) : {} F'.format(x, y, z), xy=(x, y)) + ax.annotate(f'distance: {d}', xy=(xave, yave)) + ax.annotate(f'({x}, {y}) : {z} F', xy=(x, y)) ax.set_xlim(40, 80) ax.set_ylim(40, 100) diff --git a/examples/gridding/Natural_Neighbor_Verification.py b/examples/gridding/Natural_Neighbor_Verification.py index f1f42fafa3f..5bbb6b1e9a4 100644 --- a/examples/gridding/Natural_Neighbor_Verification.py +++ b/examples/gridding/Natural_Neighbor_Verification.py @@ -80,7 +80,7 @@ delaunay_plot_2d(tri, ax=ax) for i, zval in enumerate(zp): - ax.annotate('{} F'.format(zval), xy=(pts[i, 0] + 2, pts[i, 1])) + ax.annotate(f'{zval} F', xy=(pts[i, 0] + 2, pts[i, 1])) sim_gridx = [30., 60.] sim_gridy = [30., 60.] @@ -94,11 +94,11 @@ val = natural_neighbor_point(xp, yp, zp, (sim_gridx[0], sim_gridy[0]), tri, members[0], circumcenters) -ax.annotate('grid 0: {:.3f}'.format(val), xy=(sim_gridx[0] + 2, sim_gridy[0])) +ax.annotate(f'grid 0: {val:.3f}', xy=(sim_gridx[0] + 2, sim_gridy[0])) val = natural_neighbor_point(xp, yp, zp, (sim_gridx[1], sim_gridy[1]), tri, members[1], circumcenters) -ax.annotate('grid 1: {:.3f}'.format(val), xy=(sim_gridx[1] + 2, sim_gridy[1])) +ax.annotate(f'grid 1: {val:.3f}', xy=(sim_gridx[1] + 2, sim_gridy[1])) ########################################### @@ -173,16 +173,15 @@ def draw_circle(ax, x, y, r, m, label): y_0 = yp[nn_ind] for x, y, z in zip(x_0, y_0, z_0): - ax.annotate('{}, {}: {:.3f} F'.format(x, y, z), xy=(x, y)) + ax.annotate(f'{x}, {y}: {z:.3f} F', xy=(x, y)) ax.plot(sim_gridx[0], sim_gridy[0], 'k+', markersize=10) -ax.annotate('{}, {}'.format(sim_gridx[0], sim_gridy[0]), xy=(sim_gridx[0] + 2, sim_gridy[0])) +ax.annotate(f'{sim_gridx[0]}, {sim_gridy[0]}', xy=(sim_gridx[0] + 2, sim_gridy[0])) ax.plot(cc[:, 0], cc[:, 1], 'ks', markersize=15, fillstyle='none', label='natural neighbor\ncircumcenters') for center in cc: - ax.annotate('{:.3f}, {:.3f}'.format(center[0], center[1]), - xy=(center[0] + 1, center[1] + 1)) + ax.annotate(f'{center[0]:.3f}, {center[1]:.3f}', xy=(center[0] + 1, center[1] + 1)) tris = tri.points[tri.simplices[members[0]]] for triangle in tris: @@ -202,7 +201,7 @@ def draw_polygon_with_info(ax, polygon, off_x=0, off_y=0): [pt[1], pts[(i + 1) % len(pts)][1]], 'k-') avex, avey = np.mean(pts, axis=0) - ax.annotate('area: {:.3f}'.format(geometry.area(pts)), xy=(avex + off_x, avey + off_y), + ax.annotate(f'area: {geometry.area(pts):.3f}', xy=(avex + off_x, avey + off_y), fontsize=12) diff --git a/examples/isentropic_example.py b/examples/isentropic_example.py index ba04dec2e88..a14038191a8 100644 --- a/examples/isentropic_example.py +++ b/examples/isentropic_example.py @@ -127,13 +127,13 @@ clevisent = np.arange(0, 1000, 25) cs = ax.contour(lon, lat, isentprs[level, :, :], clevisent, colors='k', linewidths=1.0, linestyles='solid', transform=ccrs.PlateCarree()) -ax.clabel(cs, fontsize=10, inline=1, inline_spacing=7, - fmt='%i', rightside_up=True, use_clabeltext=True) +cs.clabel(fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, + use_clabeltext=True) # Plot RH cf = ax.contourf(lon, lat, isentrh[level, :, :], range(10, 106, 5), cmap=plt.cm.gist_earth_r, transform=ccrs.PlateCarree()) -cb = fig.colorbar(cf, orientation='horizontal', extend='max', aspect=65, shrink=0.5, pad=0.05, +cb = fig.colorbar(cf, orientation='horizontal', aspect=65, shrink=0.5, pad=0.05, extendrect='True') cb.set_label('Relative Humidity', size='x-large') @@ -142,8 +142,8 @@ regrid_shape=20, transform=ccrs.PlateCarree()) # Make some titles -ax.set_title('{:.0f} K Isentropic Pressure (hPa), Wind (kt), Relative Humidity (percent)' - .format(isentlevs[level].m), loc='left') +ax.set_title(f'{isentlevs[level]:~.0f} Isentropic Pressure (hPa), Wind (kt), ' + 'Relative Humidity (percent)', loc='left') add_timestamp(ax, times[0].values.astype('datetime64[ms]').astype('O'), y=0.02, high_contrast=True) fig.tight_layout() @@ -173,13 +173,13 @@ clevmsf = np.arange(0, 4000, 5) cs = ax.contour(lon, lat, msf[level, :, :], clevmsf, colors='k', linewidths=1.0, linestyles='solid', transform=ccrs.PlateCarree()) -ax.clabel(cs, fontsize=10, inline=1, inline_spacing=7, - fmt='%i', rightside_up=True, use_clabeltext=True) +cs.clabel(fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, + use_clabeltext=True) # Plot RH cf = ax.contourf(lon, lat, isentrh[level, :, :], range(10, 106, 5), cmap=plt.cm.gist_earth_r, transform=ccrs.PlateCarree()) -cb = fig.colorbar(cf, orientation='horizontal', extend='max', aspect=65, shrink=0.5, pad=0.05, +cb = fig.colorbar(cf, orientation='horizontal', aspect=65, shrink=0.5, pad=0.05, extendrect='True') cb.set_label('Relative Humidity', size='x-large') @@ -188,8 +188,8 @@ regrid_shape=20, transform=ccrs.PlateCarree()) # Make some titles -ax.set_title('{:.0f} K Montgomery Streamfunction '.format(isentlevs[level].m) - + r'($10^{-2} m^2 s^{-2}$), Wind (kt), Relative Humidity (percent)', loc='left') +ax.set_title(f'{isentlevs[level]:~.0f} Montgomery Streamfunction ' + r'($10^{-2} m^2 s^{-2}$), Wind (kt), Relative Humidity (percent)', loc='left') add_timestamp(ax, times[0].values.astype('datetime64[ms]').astype('O'), y=0.02, pretext='Valid: ', high_contrast=True) diff --git a/examples/meteogram_metpy.py b/examples/meteogram_metpy.py index 5fdddfb5840..b830442b145 100644 --- a/examples/meteogram_metpy.py +++ b/examples/meteogram_metpy.py @@ -25,7 +25,7 @@ def calc_mslp(t, p, h): # Make meteogram plot -class Meteogram(object): +class Meteogram: """ Plot a time series of meteorological data from a particular station as a meteogram with standard variables to visualize, including thermodynamic, kinematic, and pressure. The functions below control the plotting of each @@ -51,7 +51,7 @@ def __init__(self, fig, dates, probeid, time=None, axis=0): self.axis_num = 0 self.dates = mpl.dates.date2num(dates) self.time = time.strftime('%Y-%m-%d %H:%M UTC') - self.title = 'Latest Ob Time: {0}\nProbe ID: {1}'.format(self.time, probeid) + self.title = f'Latest Ob Time: {self.time}\nProbe ID: {probeid}' def plot_winds(self, ws, wd, wsmax, plot_range=None): """ diff --git a/examples/sigma_to_pressure_interpolation.py b/examples/sigma_to_pressure_interpolation.py index f03709f105e..f86706a87d3 100644 --- a/examples/sigma_to_pressure_interpolation.py +++ b/examples/sigma_to_pressure_interpolation.py @@ -74,24 +74,23 @@ # Plot the heights cs = ax.contour(lon, lat, height[FH, 0, :, :], transform=ccrs.PlateCarree(), colors='k', linewidths=1.0, linestyles='solid') -ax.clabel(cs, fontsize=10, inline=1, inline_spacing=7, - fmt='%i', rightside_up=True, use_clabeltext=True) +cs.clabel(fontsize=10, inline=1, inline_spacing=7, fmt='%i', rightside_up=True, + use_clabeltext=True) # Contour the temperature cf = ax.contourf(lon, lat, temp[FH, 0, :, :], range(-20, 20, 1), cmap=plt.cm.RdBu_r, transform=ccrs.PlateCarree()) -cb = fig.colorbar(cf, orientation='horizontal', extend='max', aspect=65, shrink=0.5, - pad=0.05, extendrect='True') +cb = fig.colorbar(cf, orientation='horizontal', aspect=65, shrink=0.5, pad=0.05, + extendrect='True') cb.set_label('Celsius', size='x-large') ax.set_extent([-106.5, -90.4, 34.5, 46.75], crs=ccrs.PlateCarree()) # Make the axis title -ax.set_title('{:.0f} hPa Heights (m) and Temperature (C)'.format(plevs[0].m), loc='center', - fontsize=10) +ax.set_title(f'{plevs[0]:~.0f} Heights (m) and Temperature (C)', loc='center', fontsize=10) # Set the figure title -fig.suptitle('WRF-ARW Forecast VALID: {:s} UTC'.format(str(vtimes[FH])), fontsize=14) +fig.suptitle(f'WRF-ARW Forecast VALID: {vtimes[FH]} UTC', fontsize=14) add_timestamp(ax, vtimes[FH], y=0.02, high_contrast=True) plt.show() diff --git a/src/metpy/calc/tools.py b/src/metpy/calc/tools.py index d20e79379e6..eadaa0b2dea 100644 --- a/src/metpy/calc/tools.py +++ b/src/metpy/calc/tools.py @@ -176,7 +176,7 @@ def find_intersections(x, a, b, direction='all', log_x=False): elif direction == 'all': return intersect_x[duplicate_mask], intersect_y[duplicate_mask] else: - raise ValueError('Unknown option for direction: {0}'.format(str(direction))) + raise ValueError(f'Unknown option for direction: {direction}') return intersect_x[mask & duplicate_mask], intersect_y[mask & duplicate_mask] diff --git a/src/metpy/cbook.py b/src/metpy/cbook.py index 40f6514f0dc..ece00a8b595 100644 --- a/src/metpy/cbook.py +++ b/src/metpy/cbook.py @@ -109,7 +109,7 @@ def result_type(value): elif hasattr(value, 'magnitude'): return np.result_type(value.magnitude) else: - raise TypeError('Cannot determine dtype for type {}'.format(type(value))) + raise TypeError(f'Cannot determine dtype for type {type(value)}') __all__ = ('Registry', 'broadcast_indices', 'get_test_data', 'iterable', 'result_type') diff --git a/src/metpy/deprecation.py b/src/metpy/deprecation.py index 0043d95ed79..942f6fb369c 100644 --- a/src/metpy/deprecation.py +++ b/src/metpy/deprecation.py @@ -140,7 +140,7 @@ def _generate_deprecation_message(since, message='', name='', altmessage = '' if alternative: - altmessage = ' Use {} instead.'.format(alternative) + altmessage = f' Use {alternative} instead.' message = message + altmessage diff --git a/src/metpy/interpolate/one_dimension.py b/src/metpy/interpolate/one_dimension.py index 0e9e85fceff..38e1cd14a57 100644 --- a/src/metpy/interpolate/one_dimension.py +++ b/src/metpy/interpolate/one_dimension.py @@ -44,7 +44,7 @@ def interpolate_nans_1d(x, y, kind='linear'): elif kind == 'log': y[nans] = np.interp(np.log(x[nans]), np.log(x[~nans]), y[~nans]) else: - raise ValueError('Unknown option for kind: {0}'.format(str(kind))) + raise ValueError(f'Unknown option for kind: {kind}') return y[x_sort_args] diff --git a/src/metpy/io/_tools.py b/src/metpy/io/_tools.py index 3855415742c..a7133396430 100644 --- a/src/metpy/io/_tools.py +++ b/src/metpy/io/_tools.py @@ -101,7 +101,7 @@ def unpack_from(self, buff, offset=0): return self._create(super().unpack_from(buff, offset)) -class Enum(object): +class Enum: """Map values to specific strings.""" def __init__(self, *args, **kwargs): @@ -114,10 +114,10 @@ def __init__(self, *args, **kwargs): def __call__(self, val): """Map an integer to the string representation.""" - return self.val_map.get(val, 'Unknown ({})'.format(val)) + return self.val_map.get(val, f'Unknown ({val})') -class Bits(object): +class Bits: """Breaks an integer into a specified number of True/False bits.""" def __init__(self, num_bits): @@ -129,7 +129,7 @@ def __call__(self, val): return [bool((val >> i) & 0x1) for i in self._bits] -class BitField(object): +class BitField: """Convert an integer to a string for each bit.""" def __init__(self, *names): @@ -153,7 +153,7 @@ def __call__(self, val): return bits[0] if len(bits) == 1 else bits -class Array(object): +class Array: """Use a Struct as a callable to unpack a bunch of bytes as a list.""" def __init__(self, fmt): @@ -165,7 +165,7 @@ def __call__(self, buf): return list(self._struct.unpack(buf)) -class IOBuffer(object): +class IOBuffer: """Holds bytes from a buffer to simplify parsing and random access.""" def __init__(self, source): diff --git a/src/metpy/io/gini.py b/src/metpy/io/gini.py index e2e1d7896a9..eb099a2ba88 100644 --- a/src/metpy/io/gini.py +++ b/src/metpy/io/gini.py @@ -269,7 +269,7 @@ def _make_proj_var(self): attrs['standard_parallel'] = prod_desc2.lat_in else: raise NotImplementedError( - 'Unhandled GINI Projection: {}'.format(self.prod_desc.projection)) + f'Unhandled GINI Projection: {self.prod_desc.projection}') return 'projection', Variable((), 0, attrs) diff --git a/src/metpy/io/metar_parser.py b/src/metpy/io/metar_parser.py index 7931c1de3be..6a09f28762b 100644 --- a/src/metpy/io/metar_parser.py +++ b/src/metpy/io/metar_parser.py @@ -2,20 +2,19 @@ import re -class TreeNode(object): +class TreeNode: def __init__(self, text, offset, elements=None): self.text = text self.offset = offset self.elements = elements or [] def __iter__(self): - for el in self.elements: - yield el + yield from self.elements class TreeNode1(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode1, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.metar = elements[0] self.siteid = elements[1] self.datetime = elements[2] @@ -33,56 +32,56 @@ def __init__(self, text, offset, elements): class TreeNode2(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode2, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode3(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode3, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode4(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode4, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.wind_dir = elements[1] self.wind_spd = elements[2] class TreeNode5(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode5, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode6(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode6, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode7(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode7, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode8(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode8, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode9(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode9, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] class TreeNode10(TreeNode): def __init__(self, text, offset, elements): - super(TreeNode10, self).__init__(text, offset, elements) + super().__init__(text, offset, elements) self.sep = elements[0] self.temp = elements[2] self.dewp = elements[4] @@ -95,7 +94,7 @@ class ParseError(SyntaxError): FAILURE = object() -class Grammar(object): +class Grammar: REGEX_1 = re.compile('^[0-9A-Z]') REGEX_2 = re.compile('^[0-9A-Z]') REGEX_3 = re.compile('^[0-9A-Z]') diff --git a/src/metpy/io/nexrad.py b/src/metpy/io/nexrad.py index 24fbbd8e694..2ec4265cdf3 100644 --- a/src/metpy/io/nexrad.py +++ b/src/metpy/io/nexrad.py @@ -31,7 +31,7 @@ def version(val): ver = val / 100. else: ver = val / 10. - return '{:.1f}'.format(ver) + return f'{ver:.1f}' def scaler(scale): @@ -65,7 +65,7 @@ def bzip_blocks_decompress_all(data): try: frames.extend(bz2.decompress(data[offset:offset + block_cmp_bytes])) offset += block_cmp_bytes - except IOError: + except OSError: # If we've decompressed any frames, this is an error mid-stream, so warn, stop # trying to decompress and let processing proceed if frames: @@ -113,7 +113,7 @@ def remap_status(val): @exporter.export -class Level2File(object): +class Level2File: r"""Handle reading the NEXRAD Level 2 data and its various messages. This class attempts to decode every byte that is in a given data file. @@ -246,7 +246,7 @@ def _read_data(self): # Try to handle the message. If we don't handle it, skipping # past it is handled at the end anyway. - decoder = '_decode_msg{:d}'.format(msg_hdr.msg_type) + decoder = f'_decode_msg{msg_hdr.msg_type:d}' if hasattr(self, decoder): getattr(self, decoder)(msg_hdr) else: @@ -756,7 +756,7 @@ def inner(seq): # Default is to use numpy array indexing to use LUT to change data bytes # into physical values. Can also have a 'labels' attribute to give # categorical labels -class DataMapper(object): +class DataMapper: """Convert packed integer data into physical units.""" # Need to find way to handle range folded @@ -957,13 +957,13 @@ def __init__(self, prod): elif codes >> 6: val *= 0.01 - label = '{:.2f}'.format(val) + label = f'{val:.2f}' elif codes >> 5: val *= 0.05 - label = '{:.2f}'.format(val) + label = f'{val:.2f}' elif codes >> 4: val *= 0.1 - label = '{:.1f}'.format(val) + label = f'{val:.1f}' if codes & 0x1: val *= -1 @@ -985,7 +985,7 @@ def __init__(self, prod): @exporter.export -class Level3File(object): +class Level3File: r"""Handle reading the wide array of NEXRAD Level 3 (NIDS) product files. This class attempts to decode every byte that is in a given product file. @@ -1658,7 +1658,7 @@ def __init__(self, filename): decomp_data = self._buffer.read_func(bz2.decompress) self._buffer.splice(comp_start, decomp_data) assert self._buffer.check_remains(self.metadata['uncompressed_size']) - except IOError: + except OSError: pass # Unpack the various blocks, if present. The factor of 2 converts from @@ -1973,7 +1973,7 @@ def _unpack_packet_special_graphic_symbol(self, code, in_sym_block): if kind not in point_feature_map: log.warning('%s: Unknown graphic symbol point kind %d/%x.', self.filename, kind, kind) - ret['type'].append('Unknown ({:d})'.format(kind)) + ret['type'].append(f'Unknown ({kind:d})') else: ret['type'].append(point_feature_map[kind]) @@ -2142,7 +2142,7 @@ def _unpack_packet_cell_trend(self, code, in_sym_block): scale = 1 vals = self._read_trends() if code in (1, 2): - ret['{} Limited'.format(key)] = [True if v > 700 else False for v in vals] + ret[f'{key} Limited'] = [True if v > 700 else False for v in vals] vals = [v - 1000 if v > 700 else v for v in vals] ret[key] = [v * scale for v in vals] diff --git a/src/metpy/io/station_data.py b/src/metpy/io/station_data.py index 408ddfd6eec..5d31a1c14ab 100644 --- a/src/metpy/io/station_data.py +++ b/src/metpy/io/station_data.py @@ -34,7 +34,7 @@ def _read_station_table(input_file=None): """ if input_file is None: input_file = get_test_data('sfstns.tbl', as_file_obj=False) - with open(input_file, 'rt') as station_file: + with open(input_file) as station_file: for line in station_file: stid = line[:9].strip() synop_id = int(line[9:16].strip()) @@ -56,7 +56,7 @@ def _read_master_text_file(input_file=None): """ if input_file is None: input_file = get_test_data('master.txt', as_file_obj=False) - with open(input_file, 'rt') as station_file: + with open(input_file) as station_file: station_file.readline() for line in station_file: state = line[:3].strip() @@ -85,7 +85,7 @@ def _read_station_text_file(input_file=None): """ if input_file is None: input_file = get_test_data('stations.txt', as_file_obj=False) - with open(input_file, 'rt') as station_file: + with open(input_file) as station_file: for line in station_file: if line[0] == '!': continue @@ -134,7 +134,7 @@ def __getitem__(self, stid): for table in self._sources: if stid in table: return table[stid] - raise KeyError('No station information for {}'.format(stid)) + raise KeyError(f'No station information for {stid}') with exporter: diff --git a/src/metpy/plots/cartopy_utils.py b/src/metpy/plots/cartopy_utils.py index dd7c5891927..2db08e72292 100644 --- a/src/metpy/plots/cartopy_utils.py +++ b/src/metpy/plots/cartopy_utils.py @@ -25,7 +25,7 @@ def geometries(self): """Return an iterator of (shapely) geometries for this feature.""" import cartopy.io.shapereader as shapereader # Ensure that the associated files are in the cache - fname = '{}_{}'.format(self.name, self.scaler.scale) + fname = f'{self.name}_{self.scaler.scale}' for extension in ['.dbf', '.shx']: get_test_data(fname + extension) path = get_test_data(fname + '.shp', as_file_obj=False) diff --git a/src/metpy/plots/ctables.py b/src/metpy/plots/ctables.py index 7aae8b7e0e9..d8c8616fac9 100644 --- a/src/metpy/plots/ctables.py +++ b/src/metpy/plots/ctables.py @@ -114,7 +114,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('({0:f}, {1:f}, {2:f})\n'.format(r / 255, g / 255, b / 255)) + outfile.write('({:f}, {:f}, {:f})\n'.format(r / 255, g / 255, b / 255)) class ColortableRegistry(dict): @@ -154,7 +154,7 @@ def scan_dir(self, path): """ for fname in glob.glob(os.path.join(path, '*' + TABLE_EXT)): if os.path.isfile(fname): - with open(fname, 'r') as fobj: + with open(fname) as fobj: try: self.add_colortable(fobj, os.path.splitext(os.path.basename(fname))[0]) log.debug('Added colortable from file: %s', fname) diff --git a/src/metpy/plots/declarative.py b/src/metpy/plots/declarative.py index 4489cf73dc6..bd5a93ba3e5 100644 --- a/src/metpy/plots/declarative.py +++ b/src/metpy/plots/declarative.py @@ -880,7 +880,7 @@ def name(self): else: ret = self.field if self.level is not None: - ret += '@{:d}'.format(self.level) + ret += f'@{self.level:d}' return ret @@ -1454,7 +1454,7 @@ def name(self): ret = '' ret += ' and '.join(f for f in self.fields) if self.level is not None: - ret += '@{:d}'.format(self.level) + ret += f'@{self.level:d}' return ret @property diff --git a/src/metpy/plots/mapping.py b/src/metpy/plots/mapping.py index 14756c01d0d..f18180f7457 100644 --- a/src/metpy/plots/mapping.py +++ b/src/metpy/plots/mapping.py @@ -11,7 +11,7 @@ from ..cbook import Registry -class CFProjection(object): +class CFProjection: """Handle parsing CF projection metadata.""" # mapping from Cartopy to CF vocabulary @@ -67,7 +67,7 @@ def to_cartopy(self): try: proj_handler = self.projection_registry[proj_name] except KeyError: - raise ValueError('Unhandled projection: {}'.format(proj_name)) + raise ValueError(f'Unhandled projection: {proj_name}') return proj_handler(self._attrs, globe) diff --git a/src/metpy/plots/skewt.py b/src/metpy/plots/skewt.py index 9d35cd161ae..4d11aec2dab 100644 --- a/src/metpy/plots/skewt.py +++ b/src/metpy/plots/skewt.py @@ -248,7 +248,7 @@ def upper_xlim(self): @exporter.export -class SkewT(object): +class SkewT: r"""Make Skew-T log-P plots of data. This class simplifies the process of creating Skew-T log-P plots in @@ -654,7 +654,7 @@ def shade_area(self, y, x1, x2=0, which='both', **kwargs): fill_args = fill_properties[which] fill_args.update(kwargs) except KeyError: - raise ValueError('Unknown option for which: {0}'.format(str(which))) + raise ValueError(f'Unknown option for which: {which}') arrs = y, x1, x2 @@ -742,7 +742,7 @@ def shade_cin(self, pressure, t, t_parcel, dewpoint=None, **kwargs): @exporter.export -class Hodograph(object): +class Hodograph: r"""Make a hodograph of wind data. Plots the u and v components of the wind along the x and y axes, respectively. diff --git a/src/metpy/plots/station_plot.py b/src/metpy/plots/station_plot.py index 17f5807e264..70e83fa4c77 100644 --- a/src/metpy/plots/station_plot.py +++ b/src/metpy/plots/station_plot.py @@ -15,7 +15,7 @@ @exporter.export -class StationPlot(object): +class StationPlot: """Make a standard meteorological station plot. Plots values, symbols, or text spaced around a central location. Can also plot wind diff --git a/src/metpy/plots/wx_symbols.py b/src/metpy/plots/wx_symbols.py index 39134409be0..622d1a689d5 100644 --- a/src/metpy/plots/wx_symbols.py +++ b/src/metpy/plots/wx_symbols.py @@ -62,7 +62,7 @@ def wx_code_to_numeric(codes): return np.array(wx_sym_list) -class CodePointMapping(object): +class CodePointMapping: """Map integer values to font code points.""" def __init__(self, num, font_start, font_jumps=None, char_jumps=None): diff --git a/src/metpy/testing.py b/src/metpy/testing.py index cdd8d8a7eaa..b58d4cab287 100644 --- a/src/metpy/testing.py +++ b/src/metpy/testing.py @@ -37,7 +37,7 @@ def get_upper_air_data(date, station): dict : upper air data """ - sounding_key = '{:%Y-%m-%dT%HZ}_{}'.format(date, station) + sounding_key = f'{date:%Y-%m-%dT%HZ}_{station}' sounding_files = {'2016-05-22T00Z_DDC': 'may22_sounding.txt', '2013-01-20T12Z_OUN': 'jan20_sounding.txt', '1999-05-04T00Z_OUN': 'may4_sounding.txt', diff --git a/src/metpy/units.py b/src/metpy/units.py index 74743d10a67..14717b2ea1b 100644 --- a/src/metpy/units.py +++ b/src/metpy/units.py @@ -222,10 +222,9 @@ def wrapper(*args, **kwargs): # If there are any bad units, emit a proper error message making it clear # what went wrong. if bad: - msg = '`{}` given arguments with incorrect units: {}.'.format( - func.__name__, - ', '.join('`{}` requires "{}" but given "{}"'.format(arg, req, given) - for arg, given, req in bad)) + msg = f'`{func.__name__}` given arguments with incorrect units: ' + msg += ', '.join(f'`{arg}` requires "{req}" but given "{given}"' + for arg, given, req in bad) if 'none' in msg: msg += ('\nAny variable `x` can be assigned a unit as follows:\n' ' from metpy.units import units\n' diff --git a/src/metpy/xarray.py b/src/metpy/xarray.py index 3d1f18b1c4e..ea22a5691c9 100644 --- a/src/metpy/xarray.py +++ b/src/metpy/xarray.py @@ -685,7 +685,7 @@ def parse_cf(self, varname=None, coordinates=None): except KeyError: log.warning( 'Could not find variable corresponding to the value of ' - 'grid_mapping: {}'.format(proj_name)) + f'grid_mapping: {proj_name}') else: crs = CFProjection(proj_var.attrs) diff --git a/tests/interpolate/test_grid.py b/tests/interpolate/test_grid.py index cc473e5a32c..9eec547cbfb 100644 --- a/tests/interpolate/test_grid.py +++ b/tests/interpolate/test_grid.py @@ -264,7 +264,7 @@ def test_interpolate_to_grid(method, test_coords, boundary_coords): _, _, img = interpolate_to_grid(xp, yp, z, hres=10, interp_type=method, **extra_kw) - with get_test_data('{0}_test.npz'.format(method)) as fobj: + with get_test_data(f'{method}_test.npz') as fobj: truth = np.load(fobj)['img'] assert_array_almost_equal(truth, img) diff --git a/tests/interpolate/test_points.py b/tests/interpolate/test_points.py index c3a8e8fc2ff..9e2c6ee1c65 100644 --- a/tests/interpolate/test_points.py +++ b/tests/interpolate/test_points.py @@ -177,7 +177,7 @@ def test_interpolate_to_points(method, test_data): img = interpolate_to_points(obs_points, z, test_points, interp_type=method, **extra_kw) - with get_test_data('{}_test.npz'.format(method)) as fobj: + with get_test_data(f'{method}_test.npz') as fobj: truth = np.load(fobj)['img'].reshape(-1) assert_array_almost_equal(truth, img) diff --git a/tests/test_deprecation.py b/tests/test_deprecation.py index 737f6858bdc..d5aa1f3b119 100644 --- a/tests/test_deprecation.py +++ b/tests/test_deprecation.py @@ -8,7 +8,7 @@ from metpy import deprecation -class FakeyMcFakeface(object): +class FakeyMcFakeface: """Our faked object for testing.""" @classmethod diff --git a/tests/test_xarray.py b/tests/test_xarray.py index 7503c7e0c4d..886e656ffc4 100644 --- a/tests/test_xarray.py +++ b/tests/test_xarray.py @@ -2,8 +2,6 @@ # Distributed under the terms of the BSD 3-Clause License. # SPDX-License-Identifier: BSD-3-Clause """Test the operation of MetPy's XArray accessors.""" -from __future__ import absolute_import - from collections import OrderedDict import cartopy.crs as ccrs