From 707c7db5bd303657b1e8eabcb0a1995a5d5c8aa2 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 12:37:39 -0700 Subject: [PATCH 01/14] pyupgrade --py36-plus --- .../plot_partial_module_shading_simple.py | 4 +- docs/examples/plot_passias_diffuse_shading.py | 4 +- docs/examples/plot_single_axis_tracking.py | 2 +- docs/examples/plot_transposition_gain.py | 2 +- docs/sphinx/source/conf.py | 19 ++++--- pvlib/atmosphere.py | 4 +- pvlib/forecast.py | 36 ++++++------- pvlib/iam.py | 16 +++--- pvlib/inverter.py | 1 - pvlib/irradiance.py | 8 +-- pvlib/location.py | 6 +-- pvlib/modelchain.py | 54 +++++++++---------- pvlib/pvsystem.py | 32 +++++------ pvlib/singlediode.py | 1 - pvlib/soiling.py | 1 - pvlib/solarposition.py | 2 +- pvlib/tests/iotools/test_pvgis.py | 4 +- pvlib/tests/iotools/test_srml.py | 4 +- pvlib/tests/test_iam.py | 1 - pvlib/tests/test_inverter.py | 2 - pvlib/tests/test_soiling.py | 1 - pvlib/tests/test_spa.py | 2 +- pvlib/tracking.py | 12 ++--- 23 files changed, 105 insertions(+), 113 deletions(-) diff --git a/docs/examples/plot_partial_module_shading_simple.py b/docs/examples/plot_partial_module_shading_simple.py index ec96d9ca45..8f05a80af5 100644 --- a/docs/examples/plot_partial_module_shading_simple.py +++ b/docs/examples/plot_partial_module_shading_simple.py @@ -322,8 +322,8 @@ def find_pmp(df): plt.imshow(results_pivot, origin='lower', aspect='auto') plt.xlabel('shaded fraction') plt.ylabel('diffuse fraction') -xlabels = ["{:0.02f}".format(fs) for fs in results_pivot.columns[::5]] -ylabels = ["{:0.02f}".format(fd) for fd in results_pivot.index] +xlabels = [f"{fs:0.02f}" for fs in results_pivot.columns[::5]] +ylabels = [f"{fd:0.02f}" for fd in results_pivot.index] plt.xticks(range(0, 5*len(xlabels), 5), xlabels) plt.yticks(range(0, len(ylabels)), ylabels) plt.title('Module P_mp across shading conditions') diff --git a/docs/examples/plot_passias_diffuse_shading.py b/docs/examples/plot_passias_diffuse_shading.py index 989e977fdb..828cf141a1 100644 --- a/docs/examples/plot_passias_diffuse_shading.py +++ b/docs/examples/plot_passias_diffuse_shading.py @@ -45,7 +45,7 @@ for k in [1, 1.5, 2, 2.5, 3, 4, 5, 7, 10]: gcr = 1/k psi = shading.masking_angle_passias(surface_tilt, gcr) - plt.plot(surface_tilt, psi, label='k={}'.format(k)) + plt.plot(surface_tilt, psi, label=f'k={k}') plt.xlabel('Inclination angle [degrees]') plt.ylabel('Average masking angle [degrees]') @@ -71,7 +71,7 @@ shading_loss = shading.sky_diffuse_passias(psi) transposition_ratio = irradiance.isotropic(surface_tilt, dhi=1.0) relative_diffuse = transposition_ratio * (1-shading_loss) * 100 # % - plt.plot(surface_tilt, relative_diffuse, label='k={}'.format(k)) + plt.plot(surface_tilt, relative_diffuse, label=f'k={k}') plt.xlabel('Inclination angle [degrees]') plt.ylabel('Relative diffuse irradiance [%]') diff --git a/docs/examples/plot_single_axis_tracking.py b/docs/examples/plot_single_axis_tracking.py index 75ea3ba1ca..cd318b61d6 100644 --- a/docs/examples/plot_single_axis_tracking.py +++ b/docs/examples/plot_single_axis_tracking.py @@ -70,7 +70,7 @@ backtracking_position = backtracking_angles['tracker_theta'].fillna(0) backtracking_position.plot(title='Backtracking Curve', - label='GCR:{:0.01f}'.format(gcr), + label=f'GCR:{gcr:0.01f}', ax=ax) plt.legend() diff --git a/docs/examples/plot_transposition_gain.py b/docs/examples/plot_transposition_gain.py index 79c646c4a5..13ac8f61e5 100644 --- a/docs/examples/plot_transposition_gain.py +++ b/docs/examples/plot_transposition_gain.py @@ -76,7 +76,7 @@ def calculate_poa(tmy, solar_position, surface_tilt, surface_azimuth): for tilt in range(0, 50, 10): # we will hardcode azimuth=180 (south) for all fixed-tilt cases poa_irradiance = calculate_poa(tmy, solar_position, tilt, 180) - column_name = "FT-{}".format(tilt) + column_name = f"FT-{tilt}" # TMYs are hourly, so we can just sum up irradiance [W/m^2] to get # insolation [Wh/m^2]: df_monthly[column_name] = poa_irradiance.resample('m').sum() diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py index 571f8eb780..c7d8fa8dd1 100644 --- a/docs/sphinx/source/conf.py +++ b/docs/sphinx/source/conf.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- # # PVLIB_Python documentation build configuration file, created by # sphinx-quickstart on Fri Nov 7 15:56:33 2014. @@ -80,8 +79,8 @@ def __getattr__(cls, name): master_doc = 'index' # General information about the project. -project = u'pvlib-python' -copyright = u'2015, Sandia National Labs, Rob Andrews, University of Arizona, github contributors' +project = 'pvlib-python' +copyright = '2015, Sandia National Labs, Rob Andrews, University of Arizona, github contributors' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -251,8 +250,8 @@ def setup(app): # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'PVLIB_Python.tex', u'PVLIB\\_Python Documentation', - u'Sandia National Labs, Rob Andrews, University of Arizona, github contributors', 'manual'), + ('index', 'PVLIB_Python.tex', 'PVLIB\\_Python Documentation', + 'Sandia National Labs, Rob Andrews, University of Arizona, github contributors', 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -289,8 +288,8 @@ def setup(app): # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pvlib_python', u'PVLIB_Python Documentation', - [u'Sandia National Labs, Rob Andrews, University of Arizona, github contributors'], 1) + ('index', 'pvlib_python', 'PVLIB_Python Documentation', + ['Sandia National Labs, Rob Andrews, University of Arizona, github contributors'], 1) ] # If true, show URL addresses after external links. @@ -303,8 +302,8 @@ def setup(app): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'PVLIB_Python', u'PVLIB_Python Documentation', - u'Sandia National Labs, Rob Andrews, University of Arizona, github contributors', 'PVLIB_Python', 'One line description of project.', + ('index', 'PVLIB_Python', 'PVLIB_Python Documentation', + 'Sandia National Labs, Rob Andrews, University of Arizona, github contributors', 'PVLIB_Python', 'One line description of project.', 'Miscellaneous'), ] @@ -432,7 +431,7 @@ def make_github_url(pagename): # add line numbers if possible: start, end = get_linenos(obj) if start and end: - target_url += '#L{}-L{}'.format(start, end) + target_url += f'#L{start}-L{end}' # Just a normal source RST page else: diff --git a/pvlib/atmosphere.py b/pvlib/atmosphere.py index 473b19897c..ae25f52247 100644 --- a/pvlib/atmosphere.py +++ b/pvlib/atmosphere.py @@ -209,7 +209,7 @@ def get_relative_airmass(zenith, model='kastenyoung1989'): if 'kastenyoung1989' == model: am = (1.0 / (np.cos(zenith_rad) + - 0.50572*(((6.07995 + (90 - z)) ** - 1.6364)))) + 0.50572*((6.07995 + (90 - z)) ** - 1.6364))) elif 'kasten1966' == model: am = 1.0 / (np.cos(zenith_rad) + 0.15*((93.885 - z) ** - 1.253)) elif 'simple' == model: @@ -434,7 +434,7 @@ def first_solar_spectral_correction(pw, airmass_absolute, pw = pw.astype('float64') if np.min(pw) < min_pw: pw = np.maximum(pw, min_pw) - warn('Exceptionally low pw values replaced with {0} cm to prevent ' + warn('Exceptionally low pw values replaced with {} cm to prevent ' 'model divergence'.format(min_pw)) # Warn user about Pw data that is exceptionally high diff --git a/pvlib/forecast.py b/pvlib/forecast.py index 5cee0ac3f2..24e54e1015 100644 --- a/pvlib/forecast.py +++ b/pvlib/forecast.py @@ -21,7 +21,7 @@ 'module, or the module may be separated into its own package.') -class ForecastModel(object): +class ForecastModel: """ An object for querying and holding forecast model information for use within the pvlib library. @@ -143,7 +143,7 @@ def connect_to_catalog(self): self.connected = True def __repr__(self): - return '{}, {}'.format(self.model_name, self.set_type) + return f'{self.model_name}, {self.set_type}' def set_dataset(self): ''' @@ -710,9 +710,9 @@ def __init__(self, resolution='half', set_type='best'): resolution = resolution.title() if resolution not in self._resolutions: - raise ValueError('resolution must in {}'.format(self._resolutions)) + raise ValueError(f'resolution must in {self._resolutions}') - model = 'GFS {} Degree Forecast'.format(resolution) + model = f'GFS {resolution} Degree Forecast' # isobaric variables will require a vert_level to prevent # excessive data downloads @@ -746,7 +746,7 @@ def __init__(self, resolution='half', set_type='best'): 'mid_clouds', 'high_clouds'] - super(GFS, self).__init__(model_type, model, set_type, + super().__init__(model_type, model, set_type, vert_level=100000) def process_data(self, data, cloud_cover='total_clouds', **kwargs): @@ -766,7 +766,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): data: DataFrame Processed forecast data. """ - data = super(GFS, self).process_data(data, **kwargs) + data = super().process_data(data, **kwargs) data['temp_air'] = self.kelvin_to_celsius(data['temp_air']) data['wind_speed'] = self.uv_to_speed(data) irrads = self.cloud_cover_to_irradiance(data[cloud_cover], **kwargs) @@ -835,7 +835,7 @@ def __init__(self, set_type='best'): 'mid_clouds', 'high_clouds'] - super(HRRR_ESRL, self).__init__(model_type, model, set_type) + super().__init__(model_type, model, set_type) def process_data(self, data, cloud_cover='total_clouds', **kwargs): """ @@ -855,7 +855,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): Processed forecast data. """ - data = super(HRRR_ESRL, self).process_data(data, **kwargs) + data = super().process_data(data, **kwargs) data['temp_air'] = self.kelvin_to_celsius(data['temp_air']) data['wind_speed'] = self.gust_to_speed(data) # data['wind_speed'] = self.uv_to_speed(data) # GH 702 @@ -917,7 +917,7 @@ def __init__(self, set_type='best'): 'mid_clouds', 'high_clouds'] - super(NAM, self).__init__(model_type, model, set_type) + super().__init__(model_type, model, set_type) def process_data(self, data, cloud_cover='total_clouds', **kwargs): """ @@ -937,7 +937,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): Processed forecast data. """ - data = super(NAM, self).process_data(data, **kwargs) + data = super().process_data(data, **kwargs) data['temp_air'] = self.kelvin_to_celsius(data['temp_air']) data['wind_speed'] = self.gust_to_speed(data) irrads = self.cloud_cover_to_irradiance(data[cloud_cover], **kwargs) @@ -1000,7 +1000,7 @@ def __init__(self, set_type='best'): 'mid_clouds', 'high_clouds', ] - super(HRRR, self).__init__(model_type, model, set_type) + super().__init__(model_type, model, set_type) def process_data(self, data, cloud_cover='total_clouds', **kwargs): """ @@ -1019,7 +1019,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): data: DataFrame Processed forecast data. """ - data = super(HRRR, self).process_data(data, **kwargs) + data = super().process_data(data, **kwargs) wind_mapping = { 'wind_speed_u': 'u-component_of_wind_height_above_ground_0', 'wind_speed_v': 'v-component_of_wind_height_above_ground_0', @@ -1075,7 +1075,7 @@ def __init__(self, set_type='best'): 'dni', 'dhi', 'total_clouds', ] - super(NDFD, self).__init__(model_type, model, set_type) + super().__init__(model_type, model, set_type) def process_data(self, data, **kwargs): """ @@ -1094,7 +1094,7 @@ def process_data(self, data, **kwargs): """ cloud_cover = 'total_clouds' - data = super(NDFD, self).process_data(data, **kwargs) + data = super().process_data(data, **kwargs) data['temp_air'] = self.kelvin_to_celsius(data['temp_air']) irrads = self.cloud_cover_to_irradiance(data[cloud_cover], **kwargs) data = data.join(irrads, how='outer') @@ -1137,10 +1137,10 @@ def __init__(self, resolution='20', set_type='best'): resolution = str(resolution) if resolution not in self._resolutions: - raise ValueError('resolution must in {}'.format(self._resolutions)) + raise ValueError(f'resolution must in {self._resolutions}') model_type = 'Forecast Model Data' - model = 'Rapid Refresh CONUS {}km'.format(resolution) + model = f'Rapid Refresh CONUS {resolution}km' self.variables = { 'temp_air': 'Temperature_surface', 'wind_speed_gust': 'Wind_speed_gust_surface', @@ -1158,7 +1158,7 @@ def __init__(self, resolution='20', set_type='best'): 'low_clouds', 'mid_clouds', 'high_clouds', ] - super(RAP, self).__init__(model_type, model, set_type) + super().__init__(model_type, model, set_type) def process_data(self, data, cloud_cover='total_clouds', **kwargs): """ @@ -1178,7 +1178,7 @@ def process_data(self, data, cloud_cover='total_clouds', **kwargs): Processed forecast data. """ - data = super(RAP, self).process_data(data, **kwargs) + data = super().process_data(data, **kwargs) data['temp_air'] = self.kelvin_to_celsius(data['temp_air']) data['wind_speed'] = self.gust_to_speed(data) irrads = self.cloud_cover_to_irradiance(data[cloud_cover], **kwargs) diff --git a/pvlib/iam.py b/pvlib/iam.py index 243e097443..21dcd72815 100644 --- a/pvlib/iam.py +++ b/pvlib/iam.py @@ -16,11 +16,11 @@ # a dict of required parameter names for each IAM model # keys are the function names for the IAM models _IAM_MODEL_PARAMS = { - 'ashrae': set(['b']), - 'physical': set(['n', 'K', 'L']), - 'martin_ruiz': set(['a_r']), - 'sapm': set(['B0', 'B1', 'B2', 'B3', 'B4', 'B5']), - 'interp': set([]) + 'ashrae': {'b'}, + 'physical': {'n', 'K', 'L'}, + 'martin_ruiz': {'a_r'}, + 'sapm': {'B0', 'B1', 'B2', 'B3', 'B4', 'B5'}, + 'interp': set() } @@ -79,7 +79,7 @@ def ashrae(aoi, b=0.05): pvlib.iam.interp """ - iam = 1 - b * ((1 / np.cos(np.radians(aoi)) - 1)) + iam = 1 - b * (1 / np.cos(np.radians(aoi)) - 1) aoi_gte_90 = np.full_like(aoi, False, dtype='bool') np.greater_equal(np.abs(aoi), 90, where=~np.isnan(aoi), out=aoi_gte_90) iam = np.where(aoi_gte_90, 0, iam) @@ -675,7 +675,7 @@ def marion_integrate(function, surface_tilt, region, num=None): elif region == 'horizon': num = 1800 else: - raise ValueError('Invalid region: {}'.format(region)) + raise ValueError(f'Invalid region: {region}') beta = np.radians(surface_tilt) if isinstance(beta, pd.Series): @@ -697,7 +697,7 @@ def marion_integrate(function, surface_tilt, region, num=None): elif region == 'ground': mask = (phi_range >= np.pi/2) else: - raise ValueError('Invalid region: {}'.format(region)) + raise ValueError(f'Invalid region: {region}') phi_range = phi_range[mask] # fast Cartesian product of phi and psi diff --git a/pvlib/inverter.py b/pvlib/inverter.py index a742e1a567..a127bcc32b 100644 --- a/pvlib/inverter.py +++ b/pvlib/inverter.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ This module contains functions for inverter modeling and for fitting inverter models to data. diff --git a/pvlib/irradiance.py b/pvlib/irradiance.py index 6fd93ce614..e1d07699b2 100644 --- a/pvlib/irradiance.py +++ b/pvlib/irradiance.py @@ -432,7 +432,7 @@ def get_sky_diffuse(surface_tilt, surface_azimuth, solar_zenith, solar_azimuth, airmass, model=model_perez) else: - raise ValueError('invalid model selection {}'.format(model)) + raise ValueError(f'invalid model selection {model}') return sky @@ -927,9 +927,9 @@ def king(surface_tilt, dhi, ghi, solar_zenith): The diffuse component of the solar radiation. ''' - sky_diffuse = (dhi * ((1 + tools.cosd(surface_tilt))) / 2 + ghi * - ((0.012 * solar_zenith - 0.04)) * - ((1 - tools.cosd(surface_tilt))) / 2) + sky_diffuse = (dhi * (1 + tools.cosd(surface_tilt)) / 2 + ghi * + (0.012 * solar_zenith - 0.04) * + (1 - tools.cosd(surface_tilt)) / 2) sky_diffuse = np.maximum(sky_diffuse, 0) return sky_diffuse diff --git a/pvlib/location.py b/pvlib/location.py index c012954926..6bd1a256af 100644 --- a/pvlib/location.py +++ b/pvlib/location.py @@ -12,7 +12,7 @@ from pvlib import solarposition, clearsky, atmosphere, irradiance -class Location(object): +class Location: """ Location objects are convenient containers for latitude, longitude, timezone, and altitude data associated with a particular @@ -85,7 +85,7 @@ def __init__(self, latitude, longitude, tz='UTC', altitude=0, def __repr__(self): attrs = ['name', 'latitude', 'longitude', 'altitude', 'tz'] return ('Location: \n ' + '\n '.join( - ('{}: {}'.format(attr, getattr(self, attr)) for attr in attrs))) + '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) @classmethod def from_tmy(cls, tmy_metadata, tmy_data=None, **kwargs): @@ -310,7 +310,7 @@ def get_airmass(self, times=None, solar_position=None, elif model in atmosphere.TRUE_ZENITH_MODELS: zenith = solar_position['zenith'] else: - raise ValueError('{} is not a valid airmass model'.format(model)) + raise ValueError(f'{model} is not a valid airmass model') airmass_relative = atmosphere.get_relative_airmass(zenith, model) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 1f362dcfa8..2395a3acd4 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -21,18 +21,18 @@ # keys that are used to detect input data and assign data to appropriate # ModelChain attribute # for ModelChain.weather -WEATHER_KEYS = set(['ghi', 'dhi', 'dni', 'wind_speed', 'temp_air', - 'precipitable_water']) +WEATHER_KEYS = {'ghi', 'dhi', 'dni', 'wind_speed', 'temp_air', + 'precipitable_water'} # for ModelChain.total_irrad -POA_DATA_KEYS = set(['poa_global', 'poa_direct', 'poa_diffuse']) +POA_DATA_KEYS = {'poa_global', 'poa_direct', 'poa_diffuse'} # Optional keys to communicate temperature data. If provided, # 'cell_temperature' overrides ModelChain.temperature_model and sets # ModelChain.cell_temperature to the data. If 'module_temperature' is provdied, # overrides ModelChain.temperature_model with # pvlib.temperature.sapm_celL_from_module -TEMPERATURE_KEYS = set(['module_temperature', 'cell_temperature']) +TEMPERATURE_KEYS = {'module_temperature', 'cell_temperature'} DATA_KEYS = WEATHER_KEYS | POA_DATA_KEYS | TEMPERATURE_KEYS @@ -260,7 +260,7 @@ def get_orientation(strategy, **kwargs): return surface_tilt, surface_azimuth -class ModelChain(object): +class ModelChain: """ The ModelChain class to provides a standardized, high-level interface for all of the modeling steps necessary for calculating PV @@ -555,7 +555,7 @@ def getmcattr(self, attr): return out return ('ModelChain: \n ' + '\n '.join( - ('{}: {}'.format(attr, getmcattr(self, attr)) for attr in attrs))) + '{}: {}'.format(attr, getmcattr(self, attr)) for attr in attrs)) @property def orientation_strategy(self): @@ -610,18 +610,18 @@ def dc_model(self, model): def infer_dc_model(self): params = set(self.system.module_parameters.keys()) - if set(['A0', 'A1', 'C7']) <= params: + if {'A0', 'A1', 'C7'} <= params: return self.sapm, 'sapm' - elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', - 'R_s', 'Adjust']) <= params: + elif {'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', + 'R_s', 'Adjust'} <= params: return self.cec, 'cec' - elif set(['a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', - 'R_s']) <= params: + elif {'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', + 'R_s'} <= params: return self.desoto, 'desoto' - elif set(['gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref', - 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s']) <= params: + elif {'gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref', + 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s'} <= params: return self.pvsyst, 'pvsyst' - elif set(['pdc0', 'gamma_pdc']) <= params: + elif {'pdc0', 'gamma_pdc'} <= params: return self.pvwatts_dc, 'pvwatts' else: raise ValueError('could not infer DC model from ' @@ -705,11 +705,11 @@ def ac_model(self, model): def infer_ac_model(self): inverter_params = set(self.system.inverter_parameters.keys()) - if set(['C0', 'C1', 'C2']) <= inverter_params: + if {'C0', 'C1', 'C2'} <= inverter_params: return self.snlinverter - elif set(['ADRCoefficients']) <= inverter_params: + elif {'ADRCoefficients'} <= inverter_params: return self.adrinverter - elif set(['pdc0']) <= inverter_params: + elif {'pdc0'} <= inverter_params: return self.pvwatts_inverter else: raise ValueError('could not infer AC model from ' @@ -756,13 +756,13 @@ def aoi_model(self, model): def infer_aoi_model(self): params = set(self.system.module_parameters.keys()) - if set(['K', 'L', 'n']) <= params: + if {'K', 'L', 'n'} <= params: return self.physical_aoi_loss - elif set(['B5', 'B4', 'B3', 'B2', 'B1', 'B0']) <= params: + elif {'B5', 'B4', 'B3', 'B2', 'B1', 'B0'} <= params: return self.sapm_aoi_loss - elif set(['b']) <= params: + elif {'b'} <= params: return self.ashrae_aoi_loss - elif set(['a_r']) <= params: + elif {'a_r'} <= params: return self.martin_ruiz_aoi_loss else: raise ValueError('could not infer AOI model from ' @@ -816,7 +816,7 @@ def spectral_model(self, model): def infer_spectral_model(self): params = set(self.system.module_parameters.keys()) - if set(['A4', 'A3', 'A2', 'A1', 'A0']) <= params: + if {'A4', 'A3', 'A2', 'A1', 'A0'} <= params: return self.sapm_spectral_loss elif ((('Technology' in params or 'Material' in params) and @@ -878,13 +878,13 @@ def temperature_model(self, model): def infer_temperature_model(self): params = set(self.system.temperature_model_parameters.keys()) # remove or statement in v0.9 - if set(['a', 'b', 'deltaT']) <= params or ( + if {'a', 'b', 'deltaT'} <= params or ( not params and self.system.racking_model is None and self.system.module_type is None): return self.sapm_temp - elif set(['u_c', 'u_v']) <= params: + elif {'u_c', 'u_v'} <= params: return self.pvsyst_temp - elif set(['u0', 'u1']) <= params: + elif {'u0', 'u1'} <= params: return self.faiman_temp else: raise ValueError('could not infer temperature model from ' @@ -1077,8 +1077,8 @@ def _verify_df(self, data, required): """ if not set(required) <= set(data.columns): raise ValueError( - "Incomplete input data. Data needs to contain {0}. " - "Detected data contains: {1}".format(required, + "Incomplete input data. Data needs to contain {}. " + "Detected data contains: {}".format(required, list(data.columns))) return diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 2134801c8d..5f489175ce 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -22,26 +22,26 @@ # a dict of required parameter names for each DC power model _DC_MODEL_PARAMS = { - 'sapm': set([ + 'sapm': { 'A0', 'A1', 'A2', 'A3', 'A4', 'B0', 'B1', 'B2', 'B3', 'B4', 'B5', 'C0', 'C1', 'C2', 'C3', 'C4', 'C5', 'C6', 'C7', 'Isco', 'Impo', 'Voco', 'Vmpo', 'Aisc', 'Aimp', 'Bvoco', 'Mbvoc', 'Bvmpo', 'Mbvmp', 'N', 'Cells_in_Series', - 'IXO', 'IXXO', 'FD']), - 'desoto': set([ + 'IXO', 'IXXO', 'FD'}, + 'desoto': { 'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', - 'R_sh_ref', 'R_s']), - 'cec': set([ + 'R_sh_ref', 'R_s'}, + 'cec': { 'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', - 'R_sh_ref', 'R_s', 'Adjust']), - 'pvsyst': set([ + 'R_sh_ref', 'R_s', 'Adjust'}, + 'pvsyst': { 'gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_sh_0', 'R_s', 'alpha_sc', 'EgRef', - 'cells_in_series']), - 'singlediode': set([ + 'cells_in_series'}, + 'singlediode': { 'alpha_sc', 'a_ref', 'I_L_ref', 'I_o_ref', - 'R_sh_ref', 'R_s']), - 'pvwatts': set(['pdc0', 'gamma_pdc']) + 'R_sh_ref', 'R_s'}, + 'pvwatts': {'pdc0', 'gamma_pdc'} } @@ -69,7 +69,7 @@ def _combine_localized_attributes(pvsystem=None, location=None, **kwargs): # not sure if this belongs in the pvsystem module. # maybe something more like core.py? It may eventually grow to # import a lot more functionality from other modules. -class PVSystem(object): +class PVSystem: """ The PVSystem class defines a standard set of PV system attributes and modeling functions. This class describes the collection and @@ -225,7 +225,7 @@ def __repr__(self): 'inverter', 'albedo', 'racking_model', 'module_type', 'temperature_model_parameters'] return ('PVSystem:\n ' + '\n '.join( - ('{}: {}'.format(attr, getattr(self, attr)) for attr in attrs))) + '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) def get_aoi(self, solar_zenith, solar_azimuth): """Get the angle of incidence on the system. @@ -493,7 +493,7 @@ def sapm_celltemp(self, poa_global, temp_air, wind_speed): def _infer_temperature_model_params(self): # try to infer temperature model parameters from from racking_model # and module_type - param_set = '{}_{}'.format(self.racking_model, self.module_type) + param_set = f'{self.racking_model}_{self.module_type}' if param_set in temperature.TEMPERATURE_MODEL_PARAMETERS['sapm']: return temperature._temperature_model_params('sapm', param_set) elif 'freestanding' in param_set: @@ -871,7 +871,7 @@ def __repr__(self): 'albedo', 'racking_model', 'module_type', 'temperature_model_parameters'] return ('LocalizedPVSystem:\n ' + '\n '.join( - ('{}: {}'.format(attr, getattr(self, attr)) for attr in attrs))) + '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) def calcparams_desoto(effective_irradiance, temp_cell, @@ -1419,7 +1419,7 @@ def retrieve_sam(name=None, path=None): csvdata = os.path.join( data_path, 'sam-library-cec-inverters-2019-03-05.csv') else: - raise ValueError('invalid name {}'.format(name)) + raise ValueError(f'invalid name {name}') elif path is not None: if path.startswith('http'): response = urlopen(path) diff --git a/pvlib/singlediode.py b/pvlib/singlediode.py index 743629a25d..b800e1c730 100644 --- a/pvlib/singlediode.py +++ b/pvlib/singlediode.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Low-level functions for solving the single diode equation. """ diff --git a/pvlib/soiling.py b/pvlib/soiling.py index 33ffcc4b7e..811b414dff 100644 --- a/pvlib/soiling.py +++ b/pvlib/soiling.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ This module contains functions for soiling models """ diff --git a/pvlib/solarposition.py b/pvlib/solarposition.py index ee7cb24763..040f9d5f14 100644 --- a/pvlib/solarposition.py +++ b/pvlib/solarposition.py @@ -815,7 +815,7 @@ def ephemeris(time, latitude, longitude, pressure=101325, temperature=12): HrAngle = LocAST - RtAscen HrAngleR = np.radians(HrAngle) - HrAngle = HrAngle - (360 * ((abs(HrAngle) > 180))) + HrAngle = HrAngle - (360 * (abs(HrAngle) > 180)) SunAz = np.degrees(np.arctan2(-np.sin(HrAngleR), np.cos(LatR)*np.tan(DecR) - diff --git a/pvlib/tests/iotools/test_pvgis.py b/pvlib/tests/iotools/test_pvgis.py index 323ec0a936..1b5dc6a158 100644 --- a/pvlib/tests/iotools/test_pvgis.py +++ b/pvlib/tests/iotools/test_pvgis.py @@ -62,7 +62,7 @@ def meta_expected(): @pytest.fixture def csv_meta(meta_expected): return [ - '%s: %s (%s)' % (k, v['description'], v['units']) for k, v + '{}: {} ({})'.format(k, v['description'], v['units']) for k, v in meta_expected['outputs']['tmy_hourly']['variables'].items()] @@ -254,6 +254,6 @@ def test_read_pvgis_tmy_basic(expected, meta_expected): def test_read_pvgis_tmy_exception(): bad_outputformat = 'bad' - err_msg = "pvgis format '{:s}' was unknown".format(bad_outputformat) + err_msg = f"pvgis format '{bad_outputformat:s}' was unknown" with pytest.raises(ValueError, match=err_msg): read_pvgis_tmy('filename', pvgis_format=bad_outputformat) diff --git a/pvlib/tests/iotools/test_srml.py b/pvlib/tests/iotools/test_srml.py index 0209c188f7..3ffbe4ca7c 100644 --- a/pvlib/tests/iotools/test_srml.py +++ b/pvlib/tests/iotools/test_srml.py @@ -44,9 +44,9 @@ def test_read_srml_nans_exist(): @pytest.mark.flaky(reruns=RERUNS, reruns_delay=RERUNS_DELAY) def test_read_srml_dt_index(url, year, month): data = srml.read_srml(url) - start = pd.Timestamp('{:04d}{:02d}01 00:00'.format(year, month)) + start = pd.Timestamp(f'{year:04d}{month:02d}01 00:00') start = start.tz_localize('Etc/GMT+8') - end = pd.Timestamp('{:04d}{:02d}31 23:59'.format(year, month)) + end = pd.Timestamp(f'{year:04d}{month:02d}31 23:59') end = end.tz_localize('Etc/GMT+8') assert data.index[0] == start assert data.index[-1] == end diff --git a/pvlib/tests/test_iam.py b/pvlib/tests/test_iam.py index 607e35a072..1156fa28fa 100644 --- a/pvlib/tests/test_iam.py +++ b/pvlib/tests/test_iam.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """ Created on Wed Oct 2 10:14:16 2019 diff --git a/pvlib/tests/test_inverter.py b/pvlib/tests/test_inverter.py index 968b524bb6..19313f3f1a 100644 --- a/pvlib/tests/test_inverter.py +++ b/pvlib/tests/test_inverter.py @@ -1,5 +1,3 @@ -# -*- coding: utf-8 -*- - import numpy as np import pandas as pd diff --git a/pvlib/tests/test_soiling.py b/pvlib/tests/test_soiling.py index 3bdd52bde1..9e42f54fdb 100644 --- a/pvlib/tests/test_soiling.py +++ b/pvlib/tests/test_soiling.py @@ -1,4 +1,3 @@ -# -*- coding: utf-8 -*- """Test losses""" import datetime diff --git a/pvlib/tests/test_spa.py b/pvlib/tests/test_spa.py index 70b3b9090d..ecd28a5123 100644 --- a/pvlib/tests/test_spa.py +++ b/pvlib/tests/test_spa.py @@ -95,7 +95,7 @@ mix_month_actual = mix_year_actual -class SpaBase(object): +class SpaBase: """Test functions common to numpy and numba spa""" def test_julian_day_dt(self): # add 1us manually to the test timestamp (GH #940) diff --git a/pvlib/tracking.py b/pvlib/tracking.py index e457ea04fa..8451b061e5 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -75,15 +75,15 @@ def __init__(self, axis_tilt=0, axis_azimuth=0, max_angle=90, kwargs['surface_tilt'] = None kwargs['surface_azimuth'] = None - super(SingleAxisTracker, self).__init__(**kwargs) + super().__init__(**kwargs) def __repr__(self): attrs = ['axis_tilt', 'axis_azimuth', 'max_angle', 'backtrack', 'gcr', 'cross_axis_tilt'] sat_repr = ('SingleAxisTracker:\n ' + '\n '.join( - ('{}: {}'.format(attr, getattr(self, attr)) for attr in attrs))) + '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) # get the parent PVSystem info - pvsystem_repr = super(SingleAxisTracker, self).__repr__() + pvsystem_repr = super().__repr__() # remove the first line (contains 'PVSystem: \n') pvsystem_repr = '\n'.join(pvsystem_repr.split('\n')[1:]) return sat_repr + '\n' + pvsystem_repr @@ -261,9 +261,9 @@ def __init__(self, pvsystem=None, location=None, **kwargs): def __repr__(self): attrs = ['latitude', 'longitude', 'altitude', 'tz'] return ('Localized' + - super(LocalizedSingleAxisTracker, self).__repr__() + '\n ' + - '\n '.join(('{}: {}'.format(attr, getattr(self, attr)) - for attr in attrs))) + super().__repr__() + '\n ' + + '\n '.join('{}: {}'.format(attr, getattr(self, attr)) + for attr in attrs)) def singleaxis(apparent_zenith, apparent_azimuth, From 8f6f69260feeb618f4acee773799d1563248c44b Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 13:29:05 -0700 Subject: [PATCH 02/14] update license year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index cc39ec87b6..b4168b304a 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ BSD 3-Clause License -Copyright (c) 2013-2018, Sandia National Laboratories and pvlib python Development Team +Copyright (c) 2013-2020, Sandia National Laboratories and pvlib python Development Team All rights reserved. Redistribution and use in source and binary forms, with or without modification, From d200b4927e3b0d5f7beccb28a9fa8c14fcac933e Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 13:29:19 -0700 Subject: [PATCH 03/14] stickler --- docs/sphinx/source/conf.py | 37 ++++++++++++++----------------------- pvlib/modelchain.py | 15 +++++++-------- pvlib/tracking.py | 2 +- 3 files changed, 22 insertions(+), 32 deletions(-) diff --git a/docs/sphinx/source/conf.py b/docs/sphinx/source/conf.py index c7d8fa8dd1..7f89f0be3c 100644 --- a/docs/sphinx/source/conf.py +++ b/docs/sphinx/source/conf.py @@ -14,24 +14,12 @@ import sys import os -# Mock modules so RTD works -from unittest.mock import MagicMock - # for warning suppression import warnings # for generating GH links with linenumbers import inspect - -class Mock(MagicMock): - @classmethod - def __getattr__(cls, name): - return Mock() - -MOCK_MODULES = [] -sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) - import pandas as pd pd.show_versions() @@ -79,8 +67,9 @@ def __getattr__(cls, name): master_doc = 'index' # General information about the project. -project = 'pvlib-python' -copyright = '2015, Sandia National Labs, Rob Andrews, University of Arizona, github contributors' +project = 'pvlib python' +copyright = \ + '2013-2020, Sandia National Laboratories and pvlib python Development Team' # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the @@ -223,7 +212,7 @@ def __getattr__(cls, name): #html_file_suffix = None # Output file base name for HTML help builder. -htmlhelp_basename = 'PVLIB_Pythondoc' +htmlhelp_basename = 'pvlib_pythondoc' # custom CSS workarounds @@ -250,8 +239,9 @@ def setup(app): # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - ('index', 'PVLIB_Python.tex', 'PVLIB\\_Python Documentation', - 'Sandia National Labs, Rob Andrews, University of Arizona, github contributors', 'manual'), + ('index', 'pvlib_python.tex', 'pvlib\\_python Documentation', + 'Sandia National Laboratoraties and pvlib python Development Team', + 'manual'), ] # The name of an image file (relative to this directory) to place at the top of @@ -288,8 +278,8 @@ def setup(app): # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). man_pages = [ - ('index', 'pvlib_python', 'PVLIB_Python Documentation', - ['Sandia National Labs, Rob Andrews, University of Arizona, github contributors'], 1) + ('index', 'pvlib_python', 'pvlib_python Documentation', + ['Sandia National Laboratoraties and pvlib python Development Team'], 1) ] # If true, show URL addresses after external links. @@ -302,9 +292,10 @@ def setup(app): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - ('index', 'PVLIB_Python', 'PVLIB_Python Documentation', - 'Sandia National Labs, Rob Andrews, University of Arizona, github contributors', 'PVLIB_Python', 'One line description of project.', - 'Miscellaneous'), + ('index', 'pvlib python', 'pvlib python Documentation', + 'Sandia National Laboratoraties and pvlib python Development Team', + 'pvlib python', 'One line description of project.', + 'Miscellaneous'), ] # Documents to append as an appendix to all manuals. @@ -321,7 +312,7 @@ def setup(app): # Example configuration for intersphinx: refer to the Python standard library. intersphinx_mapping = { - 'python': ('https://docs.python.org/3.7/', None), + 'python': ('https://docs.python.org/3.8/', None), 'pandas': ('https://pandas.pydata.org/pandas-docs/stable/', None), 'numpy': ('https://docs.scipy.org/doc/numpy/', None), } diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 2395a3acd4..66ddc4ec80 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -22,7 +22,7 @@ # ModelChain attribute # for ModelChain.weather WEATHER_KEYS = {'ghi', 'dhi', 'dni', 'wind_speed', 'temp_air', - 'precipitable_water'} + 'precipitable_water'} # for ModelChain.total_irrad POA_DATA_KEYS = {'poa_global', 'poa_direct', 'poa_diffuse'} @@ -612,14 +612,13 @@ def infer_dc_model(self): params = set(self.system.module_parameters.keys()) if {'A0', 'A1', 'C7'} <= params: return self.sapm, 'sapm' - elif {'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', - 'R_s', 'Adjust'} <= params: + elif {'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s', + 'Adjust'} <= params: return self.cec, 'cec' - elif {'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', - 'R_s'} <= params: + elif {'a_ref', 'I_L_ref', 'I_o_ref', 'R_sh_ref', 'R_s'} <= params: return self.desoto, 'desoto' - elif {'gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref', - 'R_sh_ref', 'R_sh_0', 'R_sh_exp', 'R_s'} <= params: + elif {'gamma_ref', 'mu_gamma', 'I_L_ref', 'I_o_ref', 'R_sh_ref', + 'R_sh_0', 'R_sh_exp', 'R_s'} <= params: return self.pvsyst, 'pvsyst' elif {'pdc0', 'gamma_pdc'} <= params: return self.pvwatts_dc, 'pvwatts' @@ -1079,7 +1078,7 @@ def _verify_df(self, data, required): raise ValueError( "Incomplete input data. Data needs to contain {}. " "Detected data contains: {}".format(required, - list(data.columns))) + list(data.columns))) return def _assign_weather(self, data): diff --git a/pvlib/tracking.py b/pvlib/tracking.py index 8451b061e5..bd2f6bf577 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -263,7 +263,7 @@ def __repr__(self): return ('Localized' + super().__repr__() + '\n ' + '\n '.join('{}: {}'.format(attr, getattr(self, attr)) - for attr in attrs)) + for attr in attrs)) def singleaxis(apparent_zenith, apparent_azimuth, From 5825cc10144b2baf78959d1c52f9d63b4d1e386d Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 13:44:52 -0700 Subject: [PATCH 04/14] test invalid model in irradiance.get_sky_diffuse --- pvlib/tests/test_irradiance.py | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/pvlib/tests/test_irradiance.py b/pvlib/tests/test_irradiance.py index 8bea0816cc..0aeec3b95e 100644 --- a/pvlib/tests/test_irradiance.py +++ b/pvlib/tests/test_irradiance.py @@ -278,6 +278,13 @@ def test_sky_diffuse_zenith_close_to_90(model): assert sky_diffuse < 100 +def test_get_sky_diffuse_invalid(): + with pytest.raises(ValueError): + irradiance.get_sky_diffuse( + 30, 180, 0, 180, 1000, 1100, 100, dni_extra=1360, airmass=1, + model='invalid') + + def test_liujordan(): expected = pd.DataFrame(np.array( [[863.859736967, 653.123094076, 220.65905025]]), From 29b94024ba726fc5a5252798cc3116acda212e78 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:35:51 -0700 Subject: [PATCH 05/14] Update pvlib/atmosphere.py Co-authored-by: Mark Mikofski --- pvlib/atmosphere.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pvlib/atmosphere.py b/pvlib/atmosphere.py index ae25f52247..aab102ad06 100644 --- a/pvlib/atmosphere.py +++ b/pvlib/atmosphere.py @@ -434,8 +434,8 @@ def first_solar_spectral_correction(pw, airmass_absolute, pw = pw.astype('float64') if np.min(pw) < min_pw: pw = np.maximum(pw, min_pw) - warn('Exceptionally low pw values replaced with {} cm to prevent ' - 'model divergence'.format(min_pw)) + warn(f'Exceptionally low pw values replaced with {min_pw} cm to prevent ' + 'model divergence') # Warn user about Pw data that is exceptionally high if np.max(pw) > max_pw: From 34138d76104e906da6bde7c9bff86db6bd0795dc Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:36:39 -0700 Subject: [PATCH 06/14] Update pvlib/location.py Co-authored-by: Mark Mikofski --- pvlib/location.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/location.py b/pvlib/location.py index 6bd1a256af..c3e751b046 100644 --- a/pvlib/location.py +++ b/pvlib/location.py @@ -85,7 +85,7 @@ def __init__(self, latitude, longitude, tz='UTC', altitude=0, def __repr__(self): attrs = ['name', 'latitude', 'longitude', 'altitude', 'tz'] return ('Location: \n ' + '\n '.join( - '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) + f'{attr}: {getattr(self, attr)}' for attr in attrs)) @classmethod def from_tmy(cls, tmy_metadata, tmy_data=None, **kwargs): From 0f79353b970ffa2be353caf1e66fa92e342dc54a Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:36:47 -0700 Subject: [PATCH 07/14] Update pvlib/modelchain.py Co-authored-by: Mark Mikofski --- pvlib/modelchain.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 66ddc4ec80..2b8a1e0d90 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -555,7 +555,7 @@ def getmcattr(self, attr): return out return ('ModelChain: \n ' + '\n '.join( - '{}: {}'.format(attr, getmcattr(self, attr)) for attr in attrs)) + f'{attr}: {getmcattr(self, attr)}' for attr in attrs)) @property def orientation_strategy(self): From b68f4a50eaee1ab22ef6b0db0087242254abd51b Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:37:24 -0700 Subject: [PATCH 08/14] Update pvlib/modelchain.py Co-authored-by: Mark Mikofski --- pvlib/modelchain.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/pvlib/modelchain.py b/pvlib/modelchain.py index 2b8a1e0d90..c9ba17aa24 100644 --- a/pvlib/modelchain.py +++ b/pvlib/modelchain.py @@ -1076,9 +1076,8 @@ def _verify_df(self, data, required): """ if not set(required) <= set(data.columns): raise ValueError( - "Incomplete input data. Data needs to contain {}. " - "Detected data contains: {}".format(required, - list(data.columns))) + f"Incomplete input data. Data needs to contain {required}. " + f"Detected data contains: {list(data.columns)}") return def _assign_weather(self, data): From 9390e44e7afa92bc58712be943b9590cd6a4f321 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:37:37 -0700 Subject: [PATCH 09/14] Update pvlib/pvsystem.py Co-authored-by: Mark Mikofski --- pvlib/pvsystem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index 5f489175ce..da9899071e 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -225,7 +225,7 @@ def __repr__(self): 'inverter', 'albedo', 'racking_model', 'module_type', 'temperature_model_parameters'] return ('PVSystem:\n ' + '\n '.join( - '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) + f'{attr}: {getattr(self, attr)}' for attr in attrs)) def get_aoi(self, solar_zenith, solar_azimuth): """Get the angle of incidence on the system. From 4a9304bfd992fd493c5a3691a85d3954d2dbd5b6 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:37:45 -0700 Subject: [PATCH 10/14] Update pvlib/pvsystem.py Co-authored-by: Mark Mikofski --- pvlib/pvsystem.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/pvsystem.py b/pvlib/pvsystem.py index da9899071e..95bb6fe379 100644 --- a/pvlib/pvsystem.py +++ b/pvlib/pvsystem.py @@ -871,7 +871,7 @@ def __repr__(self): 'albedo', 'racking_model', 'module_type', 'temperature_model_parameters'] return ('LocalizedPVSystem:\n ' + '\n '.join( - '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) + f'{attr}: {getattr(self, attr)}' for attr in attrs)) def calcparams_desoto(effective_irradiance, temp_cell, From 9d5112e4ecc9723a80053aef74bec48ab44bc0f5 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:38:02 -0700 Subject: [PATCH 11/14] Update pvlib/tests/iotools/test_pvgis.py Co-authored-by: Mark Mikofski --- pvlib/tests/iotools/test_pvgis.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/tests/iotools/test_pvgis.py b/pvlib/tests/iotools/test_pvgis.py index 1b5dc6a158..91b48b8dce 100644 --- a/pvlib/tests/iotools/test_pvgis.py +++ b/pvlib/tests/iotools/test_pvgis.py @@ -62,7 +62,7 @@ def meta_expected(): @pytest.fixture def csv_meta(meta_expected): return [ - '{}: {} ({})'.format(k, v['description'], v['units']) for k, v + f'{k}: {v['description']} ({v['units']})' for k, v in meta_expected['outputs']['tmy_hourly']['variables'].items()] From 2f930bae02dd3fa89cfa85681c12752c68fa8825 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:38:11 -0700 Subject: [PATCH 12/14] Update pvlib/tracking.py Co-authored-by: Mark Mikofski --- pvlib/tracking.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pvlib/tracking.py b/pvlib/tracking.py index bd2f6bf577..74b7049559 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -81,7 +81,7 @@ def __repr__(self): attrs = ['axis_tilt', 'axis_azimuth', 'max_angle', 'backtrack', 'gcr', 'cross_axis_tilt'] sat_repr = ('SingleAxisTracker:\n ' + '\n '.join( - '{}: {}'.format(attr, getattr(self, attr)) for attr in attrs)) + f'{attr}: {getattr(self, attr)}' for attr in attrs)) # get the parent PVSystem info pvsystem_repr = super().__repr__() # remove the first line (contains 'PVSystem: \n') From 68bf73062d1634cb8d98fce564248cc7df1f49ee Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:39:07 -0700 Subject: [PATCH 13/14] Update pvlib/tracking.py Co-authored-by: Mark Mikofski --- pvlib/tracking.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/pvlib/tracking.py b/pvlib/tracking.py index 74b7049559..e8491c3599 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -262,8 +262,7 @@ def __repr__(self): attrs = ['latitude', 'longitude', 'altitude', 'tz'] return ('Localized' + super().__repr__() + '\n ' + - '\n '.join('{}: {}'.format(attr, getattr(self, attr)) - for attr in attrs)) + '\n '.join(f'{attr}: {getattr(self, attr)}' for attr in attrs)) def singleaxis(apparent_zenith, apparent_azimuth, From b67494d2afdc34b077de8c51545734ea893767c0 Mon Sep 17 00:00:00 2001 From: Will Holmgren Date: Sun, 6 Sep 2020 15:42:47 -0700 Subject: [PATCH 14/14] stickler --- pvlib/atmosphere.py | 4 ++-- pvlib/tests/iotools/test_pvgis.py | 3 ++- pvlib/tracking.py | 3 ++- 3 files changed, 6 insertions(+), 4 deletions(-) diff --git a/pvlib/atmosphere.py b/pvlib/atmosphere.py index aab102ad06..ff1ce8d4d5 100644 --- a/pvlib/atmosphere.py +++ b/pvlib/atmosphere.py @@ -434,8 +434,8 @@ def first_solar_spectral_correction(pw, airmass_absolute, pw = pw.astype('float64') if np.min(pw) < min_pw: pw = np.maximum(pw, min_pw) - warn(f'Exceptionally low pw values replaced with {min_pw} cm to prevent ' - 'model divergence') + warn(f'Exceptionally low pw values replaced with {min_pw} cm to ' + 'prevent model divergence') # Warn user about Pw data that is exceptionally high if np.max(pw) > max_pw: diff --git a/pvlib/tests/iotools/test_pvgis.py b/pvlib/tests/iotools/test_pvgis.py index 91b48b8dce..1957639939 100644 --- a/pvlib/tests/iotools/test_pvgis.py +++ b/pvlib/tests/iotools/test_pvgis.py @@ -9,6 +9,7 @@ from pvlib.iotools import get_pvgis_tmy, read_pvgis_tmy from conftest import DATA_DIR, RERUNS, RERUNS_DELAY + @pytest.fixture def expected(): return pd.read_csv(DATA_DIR / 'pvgis_tmy_test.dat', index_col='time(UTC)') @@ -62,7 +63,7 @@ def meta_expected(): @pytest.fixture def csv_meta(meta_expected): return [ - f'{k}: {v['description']} ({v['units']})' for k, v + f"{k}: {v['description']} ({v['units']})" for k, v in meta_expected['outputs']['tmy_hourly']['variables'].items()] diff --git a/pvlib/tracking.py b/pvlib/tracking.py index e8491c3599..14e2f73c3b 100644 --- a/pvlib/tracking.py +++ b/pvlib/tracking.py @@ -262,7 +262,8 @@ def __repr__(self): attrs = ['latitude', 'longitude', 'altitude', 'tz'] return ('Localized' + super().__repr__() + '\n ' + - '\n '.join(f'{attr}: {getattr(self, attr)}' for attr in attrs)) + '\n '.join( + f'{attr}: {getattr(self, attr)}' for attr in attrs)) def singleaxis(apparent_zenith, apparent_azimuth,