From 1a41d3de8713d326ab6d543c5ea2ad87a9338f80 Mon Sep 17 00:00:00 2001 From: Filipe Fernandes Date: Tue, 4 Apr 2023 16:53:18 -0300 Subject: [PATCH 1/4] fix linter --- docs/conf.py | 2 +- gsw/__init__.py | 19 +++------ gsw/_utilities.py | 21 +++++----- gsw/conversions.py | 59 ++++++++++++++------------- gsw/density.py | 32 +++++++-------- gsw/freezing.py | 32 +++++++-------- gsw/geostrophy.py | 4 +- gsw/ice.py | 66 +++++++++++++++---------------- gsw/stability.py | 2 +- gsw/tests/_WIP_test_ufuncs.py | 5 +-- gsw/tests/check_functions.py | 22 +++++------ gsw/tests/list_check_functions.py | 2 +- gsw/tests/test_check_functions.py | 4 +- gsw/tests/test_geostrophy.py | 2 +- gsw/tests/test_utility.py | 3 +- gsw/tests/test_xarray.py | 8 ++-- gsw/tests/write_geo_npyfiles.py | 1 + gsw/utility.py | 4 +- pyproject.toml | 11 +++++- setup.py | 7 ++-- 20 files changed, 150 insertions(+), 156 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 988693b..b894fea 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -1,5 +1,4 @@ #!/usr/bin/env python3 -# -*- coding: utf-8 -*- # # gsw documentation build configuration file, created by # sphinx-quickstart on Mon Mar 13 15:27:45 2017. @@ -56,6 +55,7 @@ # |version| and |release|, also used in various other places throughout the # built documents. import gsw + version = release = gsw.__version__ # The language for content autogenerated by Sphinx. Refer to documentation diff --git a/gsw/__init__.py b/gsw/__init__.py index 7d28f21..937212c 100644 --- a/gsw/__init__.py +++ b/gsw/__init__.py @@ -31,21 +31,12 @@ """ -from ._fixed_wrapped_ufuncs import * - -from .stability import * -from .geostrophy import * -from .utility import * -from . import geostrophy -from . import utility -from . import stability -from . import density -from . import energy -from . import conversions - -from . import ice - +from . import conversions, density, energy, geostrophy, ice, stability, utility +from ._fixed_wrapped_ufuncs import * # noqa from .conversions import t90_from_t68 +from .geostrophy import * # noqa +from .stability import * # noqa +from .utility import * # noqa try: from ._version import __version__ diff --git a/gsw/_utilities.py b/gsw/_utilities.py index 56e2a2e..0065497 100644 --- a/gsw/_utilities.py +++ b/gsw/_utilities.py @@ -2,6 +2,7 @@ import numpy as np + def masked_to_nan(arg): """ Convert a masked array to a float ndarray with nans; ensure @@ -104,7 +105,7 @@ def indexer(shape, axis, order='C'): else: index_position = list(range(ndim)) - for k in range(kmax): + for _k in range(kmax): yield tuple(inds) for i in index_position: @@ -158,8 +159,8 @@ def __init__(self, *args, **kwargs): def __getattr__(self, name): try: return self[name] - except KeyError: - raise AttributeError("'Bunch' object has no attribute '%s'" % name) + except KeyError as err: + raise AttributeError(f"'Bunch' object has no attribute {name}. {err}") def __setattr__(self, name, value): self[name] = value @@ -208,7 +209,7 @@ def from_pyfile(self, filename): # Python 3 the scoping for list comprehensions would # lead to a NameError. Wrapping the code in a function # fixes this. - d = dict() + d = {} lines = ["def _temp_func():\n"] with open(filename) as f: lines.extend([" " + line for line in f]) @@ -232,12 +233,12 @@ def update_values(self, *args, **kw): already in the Bunch instance will raise a KeyError. """ strict = kw.pop("strict", False) - newkw = dict() + newkw = {} for d in args: newkw.update(d) newkw.update(kw) self._check_strict(strict, newkw) - dsub = dict([(k, v) for (k, v) in newkw.items() if k in self]) + dsub = {k: v for (k, v) in newkw.items() if k in self} self.update(dsub) def update_None(self, *args, **kw): @@ -246,13 +247,13 @@ def update_None(self, *args, **kw): will be updated only if it is None. """ strict = kw.pop("strict", False) - newkw = dict() + newkw = {} for d in args: newkw.update(d) newkw.update(kw) self._check_strict(strict, newkw) - dsub = dict([(k, v) for (k, v) in newkw.items() - if k in self and self[k] is None]) + dsub = {k: v for (k, v) in newkw.items() + if k in self and self[k] is None} self.update(dsub) def _check_strict(self, strict, kw): @@ -264,4 +265,4 @@ def _check_strict(self, strict, kw): ek = list(self.keys()) ek.sort() raise KeyError( - "Update keys %s don't match existing keys %s" % (bk, ek)) + f"Update keys {bk} don't match existing keys {ek}") diff --git a/gsw/conversions.py b/gsw/conversions.py index ffca20e..357b457 100644 --- a/gsw/conversions.py +++ b/gsw/conversions.py @@ -43,38 +43,37 @@ 'z_from_p', ] -from ._utilities import match_args_return - from ._fixed_wrapped_ufuncs import ( -adiabatic_lapse_rate_from_CT, -C_from_SP, -CT_from_enthalpy, -CT_from_entropy, -CT_from_pt, -CT_from_rho, -CT_from_t, -deltaSA_from_SP, -entropy_from_pt, -entropy_from_t, -pt0_from_t, -pt_from_CT, -pt_from_entropy, -pt_from_t, -SA_from_rho, -SA_from_SP, -SA_from_Sstar, -SP_from_C, -SP_from_SA, -SP_from_SK, -SP_from_SR, -SP_from_Sstar, -SR_from_SP, -Sstar_from_SA, -Sstar_from_SP, -t_from_CT, -p_from_z, -z_from_p, + C_from_SP, + CT_from_enthalpy, + CT_from_entropy, + CT_from_pt, + CT_from_rho, + CT_from_t, + SA_from_rho, + SA_from_SP, + SA_from_Sstar, + SP_from_C, + SP_from_SA, + SP_from_SK, + SP_from_SR, + SP_from_Sstar, + SR_from_SP, + Sstar_from_SA, + Sstar_from_SP, + adiabatic_lapse_rate_from_CT, + deltaSA_from_SP, + entropy_from_pt, + entropy_from_t, + p_from_z, + pt0_from_t, + pt_from_CT, + pt_from_entropy, + pt_from_t, + t_from_CT, + z_from_p, ) +from ._utilities import match_args_return @match_args_return diff --git a/gsw/density.py b/gsw/density.py index 35458d1..dca91c2 100644 --- a/gsw/density.py +++ b/gsw/density.py @@ -8,20 +8,20 @@ in their own "energy" module. """ from ._wrapped_ufuncs import ( -specvol, -alpha, -beta, -alpha_on_beta, -specvol_alpha_beta, -specvol_anom_standard, -rho, -rho_alpha_beta, -rho_t_exact, -sigma0, -sigma1, -sigma2, -sigma3, -sigma4, -sound_speed, -kappa, + alpha, + alpha_on_beta, + beta, + kappa, + rho, + rho_alpha_beta, + rho_t_exact, + sigma0, + sigma1, + sigma2, + sigma3, + sigma4, + sound_speed, + specvol, + specvol_alpha_beta, + specvol_anom_standard, ) diff --git a/gsw/freezing.py b/gsw/freezing.py index 27220cb..e8e63e8 100644 --- a/gsw/freezing.py +++ b/gsw/freezing.py @@ -3,20 +3,20 @@ """ from ._wrapped_ufuncs import ( -CT_freezing, -CT_freezing_first_derivatives, -CT_freezing_first_derivatives_poly, -CT_freezing_poly, -pot_enthalpy_ice_freezing, -pot_enthalpy_ice_freezing_first_derivatives, -pot_enthalpy_ice_freezing_first_derivatives_poly, -pot_enthalpy_ice_freezing_poly, -pressure_freezing_CT, -SA_freezing_from_CT, -SA_freezing_from_CT_poly, -SA_freezing_from_t, -SA_freezing_from_t_poly, -t_freezing, -t_freezing_first_derivatives, -t_freezing_first_derivatives_poly, + CT_freezing, + CT_freezing_first_derivatives, + CT_freezing_first_derivatives_poly, + CT_freezing_poly, + SA_freezing_from_CT, + SA_freezing_from_CT_poly, + SA_freezing_from_t, + SA_freezing_from_t_poly, + pot_enthalpy_ice_freezing, + pot_enthalpy_ice_freezing_first_derivatives, + pot_enthalpy_ice_freezing_first_derivatives_poly, + pot_enthalpy_ice_freezing_poly, + pressure_freezing_CT, + t_freezing, + t_freezing_first_derivatives, + t_freezing_first_derivatives_poly, ) diff --git a/gsw/geostrophy.py b/gsw/geostrophy.py index 53c0a52..8720192 100644 --- a/gsw/geostrophy.py +++ b/gsw/geostrophy.py @@ -5,7 +5,7 @@ import numpy as np from . import _gsw_ufuncs -from ._utilities import match_args_return, indexer +from ._utilities import indexer, match_args_return from .conversions import z_from_p __all__ = ['geo_strf_dyn_height', @@ -295,7 +295,7 @@ def geostrophic_velocity(geo_strf, lon, lat, p=0, axis=0): if lon.shape != lat.shape or lon.ndim != 1: raise ValueError('lon, lat must be 1-D and matching; found shapes' - ' %s and %s' % (lon.shape, lat.shape)) + ' {} and {}'.format(lon.shape, lat.shape)) if geo_strf.ndim not in (1, 2): raise ValueError('geo_strf must be 1-D or 2-d; found shape %s' diff --git a/gsw/ice.py b/gsw/ice.py index aac1754..e0712dc 100644 --- a/gsw/ice.py +++ b/gsw/ice.py @@ -3,37 +3,37 @@ """ from ._wrapped_ufuncs import ( -adiabatic_lapse_rate_ice, -alpha_wrt_t_ice, -chem_potential_water_ice, -cp_ice, -enthalpy_ice, -entropy_ice, -Helmholtz_energy_ice, -ice_fraction_to_freeze_seawater, -internal_energy_ice, -kappa_const_t_ice, -kappa_ice, -melting_ice_equilibrium_SA_CT_ratio, -melting_ice_equilibrium_SA_CT_ratio_poly, -melting_ice_into_seawater, -melting_ice_SA_CT_ratio, -melting_ice_SA_CT_ratio_poly, -melting_seaice_equilibrium_SA_CT_ratio, -melting_seaice_equilibrium_SA_CT_ratio_poly, -melting_seaice_into_seawater, -melting_seaice_SA_CT_ratio, -melting_seaice_SA_CT_ratio_poly, -pot_enthalpy_from_pt_ice, -pot_enthalpy_from_pt_ice_poly, -pressure_coefficient_ice, -pt0_from_t_ice, -pt_from_pot_enthalpy_ice, -pt_from_pot_enthalpy_ice_poly, -pt_from_t_ice, -rho_ice, -seaice_fraction_to_freeze_seawater, -sound_speed_ice, -specvol_ice, -t_from_pt0_ice, + Helmholtz_energy_ice, + adiabatic_lapse_rate_ice, + alpha_wrt_t_ice, + chem_potential_water_ice, + cp_ice, + enthalpy_ice, + entropy_ice, + ice_fraction_to_freeze_seawater, + internal_energy_ice, + kappa_const_t_ice, + kappa_ice, + melting_ice_equilibrium_SA_CT_ratio, + melting_ice_equilibrium_SA_CT_ratio_poly, + melting_ice_into_seawater, + melting_ice_SA_CT_ratio, + melting_ice_SA_CT_ratio_poly, + melting_seaice_equilibrium_SA_CT_ratio, + melting_seaice_equilibrium_SA_CT_ratio_poly, + melting_seaice_into_seawater, + melting_seaice_SA_CT_ratio, + melting_seaice_SA_CT_ratio_poly, + pot_enthalpy_from_pt_ice, + pot_enthalpy_from_pt_ice_poly, + pressure_coefficient_ice, + pt0_from_t_ice, + pt_from_pot_enthalpy_ice, + pt_from_pot_enthalpy_ice_poly, + pt_from_t_ice, + rho_ice, + seaice_fraction_to_freeze_seawater, + sound_speed_ice, + specvol_ice, + t_from_pt0_ice, ) diff --git a/gsw/stability.py b/gsw/stability.py index c4acbb0..9db9210 100644 --- a/gsw/stability.py +++ b/gsw/stability.py @@ -16,8 +16,8 @@ import numpy as np -from ._utilities import match_args_return, axis_slicer from ._gsw_ufuncs import grav, specvol_alpha_beta +from ._utilities import axis_slicer, match_args_return __all__ = ['Nsquared', 'Turner_Rsubrho', diff --git a/gsw/tests/_WIP_test_ufuncs.py b/gsw/tests/_WIP_test_ufuncs.py index ad39d6d..bd605d9 100644 --- a/gsw/tests/_WIP_test_ufuncs.py +++ b/gsw/tests/_WIP_test_ufuncs.py @@ -5,9 +5,8 @@ approach anyway. For now, test_check_functions is adequate, handling the wrapped ufuncs via check_functions "eval" and "exec" machinery. """ -import pytest - import numpy as np +import pytest from numpy.testing import assert_allclose import gsw @@ -44,7 +43,7 @@ def set_from_name(vname, value): if b == 'cf': cf[name] = value else: - raise ValueError("attempting to set value in %s" % (b,)) + raise ValueError(f"attempting to set value in {b}") func = getattr(gsw._gsw_ufuncs, mfunc.name) args = [eval(a) for a in mfunc.argstrings] diff --git a/gsw/tests/check_functions.py b/gsw/tests/check_functions.py index 05bb56d..eefb566 100644 --- a/gsw/tests/check_functions.py +++ b/gsw/tests/check_functions.py @@ -25,12 +25,12 @@ """ import os -import sys import re +import sys import numpy as np -from gsw import * +from gsw import * # noqa from gsw._utilities import Bunch # If we switch to using the logging module, uncomment: @@ -77,7 +77,7 @@ def group_or(line): return new -class FunctionCheck(object): +class FunctionCheck: """ Parse the line-pair for checks in gsw_check_functions. """ @@ -166,14 +166,14 @@ def record_details(self, evalargs): self.details = parts - def run(self, locals=None): + def run(self, locals_=None): try: - if locals is not None: + if locals_ is not None: _globals = globals() #dict(**globals()) - _globals.update(locals) + _globals.update(locals_) evalargs = (_globals,) else: - evalargs = tuple() + evalargs = () # The following is needed for melting_ice_into_seawater. if len(self.outstrings) > 1: @@ -184,7 +184,7 @@ def run(self, locals=None): exec(self.runline + rl_ind, *evalargs) if len(self.outstrings) == 1: if isinstance(eval(self.outstr, *evalargs), tuple): - exec("%s = %s[0]" % (self.outstr, self.outstr), *evalargs) + exec(f"{self.outstr} = {self.outstr}[0]", *evalargs) self.outlist = [eval(s, *evalargs) for s in self.outstrings] exec(self.testline, *evalargs) @@ -230,7 +230,7 @@ def parse_check_functions(mfile): Return a list of FunctionCheck instances from gsw_check_functions.m """ - with open(mfile, 'rt') as fid: + with open(mfile) as fid: mfilelines = fid.readlines() first_pass = [] @@ -321,7 +321,7 @@ def parse_check_functions(mfile): run_problems = [f for f in checks if f.exception is not None] etypes = [NameError, UnboundLocalError, TypeError, AttributeError] - ex_dict = dict() + ex_dict = {} for exc in etypes: elist = [(f.name, f.exception) for f in checks if isinstance(f.exception, exc)] @@ -351,7 +351,7 @@ def parse_check_functions(mfile): print("\n%s exceptions were raised as follows:" % len(run_problems)) for exc in etypes: print(" ", exc.__name__) - strings = [" %s : %s" % e for e in ex_dict[exc]] + strings = [" {} : {}".format(*e) for e in ex_dict[exc]] print("\n".join(strings)) print("") diff --git a/gsw/tests/list_check_functions.py b/gsw/tests/list_check_functions.py index 98f59d9..40b9d71 100644 --- a/gsw/tests/list_check_functions.py +++ b/gsw/tests/list_check_functions.py @@ -6,9 +6,9 @@ import os import numpy as np +from check_functions import parse_check_functions import gsw -from check_functions import parse_check_functions root_path = os.path.abspath(os.path.dirname(__file__)) diff --git a/gsw/tests/test_check_functions.py b/gsw/tests/test_check_functions.py index 3fbb3a6..103568d 100644 --- a/gsw/tests/test_check_functions.py +++ b/gsw/tests/test_check_functions.py @@ -3,14 +3,14 @@ """ import os -import pytest import numpy as np +import pytest +from check_functions import parse_check_functions from numpy.testing import assert_allclose import gsw from gsw._utilities import Bunch -from check_functions import parse_check_functions # Most of the tests have some nan values, so we need to suppress the warning. # Any more careful fix would likely require considerable effort. diff --git a/gsw/tests/test_geostrophy.py b/gsw/tests/test_geostrophy.py index 16b559c..a6fefaa 100644 --- a/gsw/tests/test_geostrophy.py +++ b/gsw/tests/test_geostrophy.py @@ -1,7 +1,7 @@ import os import numpy as np -from numpy.testing import assert_array_equal, assert_almost_equal +from numpy.testing import assert_almost_equal, assert_array_equal import gsw from gsw._utilities import Bunch diff --git a/gsw/tests/test_utility.py b/gsw/tests/test_utility.py index 60362f6..6de3b7f 100644 --- a/gsw/tests/test_utility.py +++ b/gsw/tests/test_utility.py @@ -1,6 +1,5 @@ -import pytest - import numpy as np +import pytest import gsw diff --git a/gsw/tests/test_xarray.py b/gsw/tests/test_xarray.py index 0d95550..431fd75 100644 --- a/gsw/tests/test_xarray.py +++ b/gsw/tests/test_xarray.py @@ -9,17 +9,15 @@ """ import os -import pytest import numpy as np -from numpy.testing import assert_allclose - import pandas as pd - +import pytest +from check_functions import parse_check_functions +from numpy.testing import assert_allclose import gsw from gsw._utilities import Bunch -from check_functions import parse_check_functions xr = pytest.importorskip('xarray') diff --git a/gsw/tests/write_geo_npyfiles.py b/gsw/tests/write_geo_npyfiles.py index a27f3ba..d91e72d 100644 --- a/gsw/tests/write_geo_npyfiles.py +++ b/gsw/tests/write_geo_npyfiles.py @@ -13,6 +13,7 @@ """ import numpy as np + import gsw from gsw._utilities import Bunch diff --git a/gsw/utility.py b/gsw/utility.py index 485a59e..d704f4d 100644 --- a/gsw/utility.py +++ b/gsw/utility.py @@ -5,7 +5,8 @@ import numpy as np from . import _gsw_ufuncs -from ._utilities import match_args_return, indexer +from ._utilities import indexer, match_args_return + @match_args_return def pchip_interp(x, y, xi, axis=0): @@ -44,7 +45,6 @@ def pchip_interp(x, y, xi, axis=0): raise ValueError('xi must be no more than 1-dimensional') nxi = xi.size x, y = np.broadcast_arrays(x, y) - shape0 = x.shape out_shape = list(x.shape) out_shape[axis] = nxi yi = np.empty(out_shape, dtype=float) diff --git a/pyproject.toml b/pyproject.toml index a19aae0..7c06322 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -77,7 +77,6 @@ select = [ "C4", # flake8-comprehensions "F", # flakes "I", # import sorting - # "T20", # flake8-print "UP", # upgrade ] target-version = "py38" @@ -94,6 +93,14 @@ exclude = [ ] [tool.ruff.per-file-ignores] -"docs/source/conf.py" = [ +"docs/conf.py" = [ "A001", ] +"gsw/_fixed_wrapped_ufuncs.py" = [ + "F403", + "F405", +] + +"gsw/_utilities.py" = [ + "B904", +] diff --git a/setup.py b/setup.py index a94b43d..6a33d6e 100644 --- a/setup.py +++ b/setup.py @@ -4,19 +4,18 @@ import os -import sys import shutil +import sys +from distutils.command.build_ext import build_ext as _build_ext import pkg_resources from setuptools import Extension, setup -from distutils.command.build_ext import build_ext as _build_ext - rootpath = os.path.abspath(os.path.dirname(__file__)) def read(*parts): - return open(os.path.join(rootpath, *parts), "r").read() + return open(os.path.join(rootpath, *parts)).read() class build_ext(_build_ext): From 92997c8140bbfd0cf58860fc0bbcc108132649f6 Mon Sep 17 00:00:00 2001 From: Filipe Fernandes Date: Thu, 6 Apr 2023 15:10:35 -0300 Subject: [PATCH 2/4] identify the rules we are ignoring --- pyproject.toml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index 7c06322..a738f0e 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -83,9 +83,9 @@ target-version = "py38" line-length = 105 ignore = [ - "F401", - "E501", - "E713", + "F401", # module imported but unused + "E501", # line too long + "E713", # test for membership should be 'not in' ] exclude = [ @@ -94,13 +94,13 @@ exclude = [ [tool.ruff.per-file-ignores] "docs/conf.py" = [ - "A001", + "A001", # variable is shadowing a python builtin ] "gsw/_fixed_wrapped_ufuncs.py" = [ - "F403", - "F405", + "F403", #'from x import *' used; unable to detect undefined names + "F405", # 'import' may be undefined, or defined from star imports ] "gsw/_utilities.py" = [ - "B904", + "B904", # Within an ``except`` clause, raise exceptions with ``raise ... from err`` ] From 291cae3408a9e5cd225d18f3ccfec637656ee387 Mon Sep 17 00:00:00 2001 From: Filipe Fernandes Date: Thu, 6 Apr 2023 15:44:18 -0300 Subject: [PATCH 3/4] f-strings --- gsw/geostrophy.py | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/gsw/geostrophy.py b/gsw/geostrophy.py index 8720192..847ac02 100644 --- a/gsw/geostrophy.py +++ b/gsw/geostrophy.py @@ -50,16 +50,15 @@ def geo_strf_dyn_height(SA, CT, p, p_ref=0, axis=0, max_dp=1.0, """ interp_methods = {'pchip' : 2, 'linear' : 1} if interp_method not in interp_methods: - raise ValueError('interp_method must be one of %s' - % (interp_methods.keys(),)) + raise ValueError(f'interp_method must be one of {interp_methods.keys()}') if SA.shape != CT.shape: - raise ValueError('Shapes of SA and CT must match; found %s and %s' - % (SA.shape, CT.shape)) + raise ValueError(f'Shapes of SA and CT must match; found {SA.shape} and {CT.shape}') if p.ndim == 1 and SA.ndim > 1: if len(p) != SA.shape[axis]: - raise ValueError('With 1-D p, len(p) must be SA.shape[axis];\n' - ' found %d versus %d on specified axis, %d' - % (len(p), SA.shape[axis], axis)) + raise ValueError( + f'With 1-D p, len(p) must be SA.shape[axis];\n' + f' found {len(p)} versus {SA.shape[axis]} on specified axis, {axis}' + ) ind = [np.newaxis] * SA.ndim ind[axis] = slice(None) p = p[tuple(ind)] @@ -294,12 +293,10 @@ def geostrophic_velocity(geo_strf, lon, lat, p=0, axis=0): lon = unwrap(lon) if lon.shape != lat.shape or lon.ndim != 1: - raise ValueError('lon, lat must be 1-D and matching; found shapes' - ' {} and {}'.format(lon.shape, lat.shape)) + raise ValueError(f'lon, lat must be 1-D and matching; found shapes {lon.shape} and {lat.shape}') if geo_strf.ndim not in (1, 2): - raise ValueError('geo_strf must be 1-D or 2-d; found shape %s' - % (geo_strf.shape,)) + raise ValueError(f'geo_strf must be 1-D or 2-d; found shape {geo_strf.shape}') laxis = 0 if axis else -1 From 03f9e97e6f756715f96d8e0141727ea0a6ea79b8 Mon Sep 17 00:00:00 2001 From: Filipe Fernandes Date: Thu, 6 Apr 2023 15:51:25 -0300 Subject: [PATCH 4/4] we'll probably have to split the xarray tests for a while --- requirements-dev.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/requirements-dev.txt b/requirements-dev.txt index 6876fea..7372d6d 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -6,6 +6,5 @@ setuptools_scm sphinx sphinx_rtd_theme twine -xarray pandas>=2 dask