Merge pull request #12247 from freqtrade/dependabot/pip/develop/ruff-0.13.0

chore(deps-dev): bump ruff from 0.12.12 to 0.13.0
This commit is contained in:
Matthias
2025-09-15 20:21:40 +02:00
committed by GitHub
18 changed files with 57 additions and 52 deletions

View File

@@ -78,5 +78,5 @@ def format_duration(td: timedelta) -> str:
"""
d = td.days
h, r = divmod(td.seconds, 3600)
m, s = divmod(r, 60)
m, _ = divmod(r, 60)
return f"{d}d {h:02d}:{m:02d}"

View File

@@ -6,7 +6,7 @@
-r requirements-freqai-rl.txt
-r docs/requirements-docs.txt
ruff==0.12.12
ruff==0.13.0
mypy==1.18.1
pre-commit==4.3.0
pytest==8.4.2

View File

@@ -658,7 +658,9 @@ def test_start_new_strategy_no_arg():
args = [
"new-strategy",
]
with pytest.raises(OperationalException, match="`new-strategy` requires --strategy to be set."):
with pytest.raises(
OperationalException, match=r"`new-strategy` requires --strategy to be set\."
):
start_new_strategy(get_args(args))
@@ -803,7 +805,7 @@ def test_get_ui_download_url_direct(mocker):
assert last_version == "0.0.1"
assert x == "http://download1.zip"
with pytest.raises(ValueError, match="UI-Version not found."):
with pytest.raises(ValueError, match=r"UI-Version not found\."):
x, last_version = get_ui_download_url("0.0.3", False)
@@ -1650,7 +1652,7 @@ def test_hyperopt_show(mocker, capsys):
pargs = get_args(args)
pargs["config"] = None
with pytest.raises(
OperationalException, match="The index of the epoch to show should be greater than -4."
OperationalException, match=r"The index of the epoch to show should be greater than -4\."
):
start_hyperopt_show(pargs)
@@ -1658,7 +1660,7 @@ def test_hyperopt_show(mocker, capsys):
pargs = get_args(args)
pargs["config"] = None
with pytest.raises(
OperationalException, match="The index of the epoch to show should be less than 4."
OperationalException, match=r"The index of the epoch to show should be less than 4\."
):
start_hyperopt_show(pargs)
@@ -2032,5 +2034,7 @@ def test_start_edge():
]
pargs = get_args(args)
with pytest.raises(OperationalException, match="The Edge module has been deprecated in 2023.9"):
with pytest.raises(
OperationalException, match=r"The Edge module has been deprecated in 2023\.9"
):
start_edge(pargs)

View File

@@ -75,7 +75,7 @@ def test_get_latest_hyperopt_file(testdatadir):
# Test with absolute path
with pytest.raises(
OperationalException,
match="--hyperopt-filename expects only the filename, not an absolute path.",
match=r"--hyperopt-filename expects only the filename, not an absolute path\.",
):
get_latest_hyperopt_file(str(testdatadir.parent), str(testdatadir.parent))
@@ -344,7 +344,7 @@ def test_create_cum_profit1(testdatadir):
assert cum_profits.iloc[0]["cum_profits"] == 0
assert pytest.approx(cum_profits.iloc[-1]["cum_profits"]) == 9.0225563e-05
with pytest.raises(ValueError, match="Trade dataframe empty."):
with pytest.raises(ValueError, match=r"Trade dataframe empty\."):
create_cum_profit(
df.set_index("date"),
bt_data[bt_data["pair"] == "NOTAPAIR"],
@@ -369,10 +369,10 @@ def test_calculate_max_drawdown(testdatadir):
underwater = calculate_underwater(bt_data)
assert isinstance(underwater, DataFrame)
with pytest.raises(ValueError, match="Trade dataframe empty."):
with pytest.raises(ValueError, match=r"Trade dataframe empty\."):
calculate_max_drawdown(DataFrame())
with pytest.raises(ValueError, match="Trade dataframe empty."):
with pytest.raises(ValueError, match=r"Trade dataframe empty\."):
calculate_underwater(DataFrame())
@@ -391,7 +391,7 @@ def test_calculate_csum(testdatadir):
assert csum_min1 == csum_min + 5
assert csum_max1 == csum_max + 5
with pytest.raises(ValueError, match="Trade dataframe empty."):
with pytest.raises(ValueError, match=r"Trade dataframe empty\."):
csum_min, csum_max = calculate_csum(DataFrame())

View File

@@ -49,7 +49,7 @@ def test_ohlcv_to_dataframe(ohlcv_history_list, caplog):
def test_trades_to_ohlcv(trades_history_df, caplog):
caplog.set_level(logging.DEBUG)
with pytest.raises(ValueError, match="Trade-list empty."):
with pytest.raises(ValueError, match=r"Trade-list empty\."):
trades_to_ohlcv(pd.DataFrame(columns=trades_history_df.columns), "1m")
df = trades_to_ohlcv(trades_history_df, "1m")

View File

@@ -859,7 +859,7 @@ def test_validate_pricing(default_conf, mocker):
default_conf["exchange"]["name"] = "binance"
ExchangeResolver.load_exchange(default_conf)
has.update({"fetchTicker": False})
with pytest.raises(OperationalException, match="Ticker pricing not available for .*"):
with pytest.raises(OperationalException, match=r"Ticker pricing not available for .*"):
ExchangeResolver.load_exchange(default_conf)
has.update({"fetchTicker": True})
@@ -868,7 +868,7 @@ def test_validate_pricing(default_conf, mocker):
ExchangeResolver.load_exchange(default_conf)
has.update({"fetchL2OrderBook": False})
with pytest.raises(OperationalException, match="Orderbook not available for .*"):
with pytest.raises(OperationalException, match=r"Orderbook not available for .*"):
ExchangeResolver.load_exchange(default_conf)
has.update({"fetchL2OrderBook": True})
@@ -877,7 +877,7 @@ def test_validate_pricing(default_conf, mocker):
default_conf["trading_mode"] = TradingMode.FUTURES
default_conf["margin_mode"] = MarginMode.ISOLATED
with pytest.raises(OperationalException, match="Ticker pricing not available for .*"):
with pytest.raises(OperationalException, match=r"Ticker pricing not available for .*"):
ExchangeResolver.load_exchange(default_conf)
@@ -3556,7 +3556,7 @@ def test_get_historic_trades_notsupported(
pair = "ETH/BTC"
with pytest.raises(
OperationalException, match="This exchange does not support downloading Trades."
OperationalException, match=r"This exchange does not support downloading Trades\."
):
exchange.get_historic_trades(pair, since=trades_history[0][0], until=trades_history[-1][0])
@@ -4442,7 +4442,7 @@ def test_get_markets(
def test_get_markets_error(default_conf, mocker):
ex = get_patched_exchange(mocker, default_conf)
mocker.patch(f"{EXMS}.markets", PropertyMock(return_value=None))
with pytest.raises(OperationalException, match="Markets were not loaded."):
with pytest.raises(OperationalException, match=r"Markets were not loaded\."):
ex.get_markets("LTC", "USDT", True, False)
@@ -5243,7 +5243,7 @@ def test__fetch_and_calculate_funding_fees(
# Return empty "refresh_latest"
mocker.patch(f"{EXMS}.refresh_latest_ohlcv", return_value={})
ex = get_patched_exchange(mocker, default_conf, api_mock, exchange=exchange)
with pytest.raises(ExchangeError, match="Could not find funding rates."):
with pytest.raises(ExchangeError, match=r"Could not find funding rates\."):
ex._fetch_and_calculate_funding_fees(
pair="ADA/USDT:USDT", amount=amount, is_short=False, open_date=d1, close_date=d2
)

View File

@@ -986,7 +986,7 @@ def test_execute_entry(
# Fail to get price...
mocker.patch(f"{EXMS}.get_rate", MagicMock(return_value=0.0))
with pytest.raises(PricingError, match="Could not determine entry price."):
with pytest.raises(PricingError, match=r"Could not determine entry price\."):
freqtrade.execute_entry(pair, stake_amount, is_short=is_short)
# In case of custom entry price

View File

@@ -357,7 +357,7 @@ def test_get_pair_precision_bt(default_conf, mocker) -> None:
pair = "UNITTEST/BTC"
backtesting.pairlists._whitelist = [pair]
ex_mock = mocker.patch(f"{EXMS}.get_precision_price", return_value=1e-5)
data, timerange = backtesting.load_bt_data()
data, _timerange = backtesting.load_bt_data()
assert data
assert backtesting.get_pair_precision(pair, dt_utc(2018, 1, 1)) == (1e-8, TICK_SIZE)
@@ -444,7 +444,7 @@ def test_backtesting_start_no_data(default_conf, mocker, caplog, testdatadir) ->
backtesting = Backtesting(default_conf)
backtesting._set_strategy(backtesting.strategylist[0])
with pytest.raises(OperationalException, match="No data found. Terminating."):
with pytest.raises(OperationalException, match=r"No data found. Terminating\."):
backtesting.start()
@@ -465,7 +465,7 @@ def test_backtesting_no_pair_left(default_conf, mocker) -> None:
default_conf["export"] = "none"
default_conf["timerange"] = "20180101-20180102"
with pytest.raises(OperationalException, match="No pair in whitelist."):
with pytest.raises(OperationalException, match=r"No pair in whitelist\."):
Backtesting(default_conf)
default_conf.update(
@@ -476,7 +476,7 @@ def test_backtesting_no_pair_left(default_conf, mocker) -> None:
)
with pytest.raises(
OperationalException, match="Detail timeframe must be smaller than strategy timeframe."
OperationalException, match=r"Detail timeframe must be smaller than strategy timeframe\."
):
Backtesting(default_conf)
@@ -517,7 +517,7 @@ def test_backtesting_pairlist_list(default_conf, mocker, tickers) -> None:
default_conf["strategy_list"] = [CURRENT_TEST_STRATEGY, "StrategyTestV2"]
with pytest.raises(
OperationalException,
match="PrecisionFilter not allowed for backtesting multiple strategies.",
match=r"PrecisionFilter not allowed for backtesting multiple strategies\.",
):
Backtesting(default_conf)

View File

@@ -280,7 +280,7 @@ def test_start_no_data(mocker, hyperopt_conf, tmp_path) -> None:
"5",
]
pargs = get_args(args)
with pytest.raises(OperationalException, match="No data found. Terminating."):
with pytest.raises(OperationalException, match=r"No data found. Terminating\."):
start_hyperopt(pargs)
# Cleanup since that failed hyperopt start leaves a lockfile.
@@ -1127,7 +1127,7 @@ def test_in_strategy_auto_hyperopt(mocker, hyperopt_conf, tmp_path, fee) -> None
assert opt.backtesting.strategy.max_open_trades != 1
opt.custom_hyperopt.generate_estimator = lambda *args, **kwargs: "ET1"
with pytest.raises(OperationalException, match="Optuna Sampler ET1 not supported."):
with pytest.raises(OperationalException, match=r"Optuna Sampler ET1 not supported\."):
opt.get_optimizer(42)

View File

@@ -11,8 +11,8 @@ from freqtrade.resolvers.hyperopt_resolver import HyperOptLossResolver
def test_hyperoptlossresolver_noname(default_conf):
with pytest.raises(
OperationalException,
match="No Hyperopt loss set. Please use `--hyperopt-loss` to specify "
"the Hyperopt-Loss class to use.",
match=r"No Hyperopt loss set. Please use `--hyperopt-loss` to specify "
r"the Hyperopt-Loss class to use\.",
):
HyperOptLossResolver.load_hyperoptloss(default_conf)

View File

@@ -1669,7 +1669,7 @@ def test_rangestabilityfilter_checks(mocker, default_conf, markets, tickers):
with pytest.raises(
OperationalException,
match="RangeStabilityFilter requires sort_direction to be either None.*",
match=r"RangeStabilityFilter requires sort_direction to be either None\.*",
):
get_patched_freqtradebot(mocker, default_conf)
@@ -2526,7 +2526,7 @@ def test_MarketCapPairList_exceptions(mocker, default_conf_usdt, caplog):
}
]
with pytest.raises(
OperationalException, match="Category layer250 not in coingecko category list."
OperationalException, match=r"Category layer250 not in coingecko category list\."
):
PairListManager(exchange, default_conf_usdt)

View File

@@ -82,7 +82,7 @@ def test_fetch_pairlist_mock_response_html(mocker, rpl_config):
exchange, pairlistmanager, rpl_config, rpl_config["pairlists"][0], 0
)
with pytest.raises(OperationalException, match="RemotePairList is not of type JSON."):
with pytest.raises(OperationalException, match=r"RemotePairList is not of type JSON\."):
remote_pairlist.fetch_pairlist()

View File

@@ -393,7 +393,7 @@ def test_rpc_delete_trade(mocker, default_conf, fee, markets, caplog, is_short):
freqtradebot.strategy.order_types["stoploss_on_exchange"] = True
create_mock_trades(fee, is_short)
rpc = RPC(freqtradebot)
with pytest.raises(RPCException, match="Trade with id '200' not found."):
with pytest.raises(RPCException, match=r"Trade with id '200' not found\."):
rpc._rpc_delete("200")
trades = Trade.session.scalars(select(Trade)).all()
@@ -1204,7 +1204,7 @@ def test_rpc_force_entry(mocker, default_conf, ticker, fee, limit_buy_order_open
patch_get_signal(freqtradebot)
rpc = RPC(freqtradebot)
pair = "ETH/BTC"
with pytest.raises(RPCException, match="Maximum number of trades is reached."):
with pytest.raises(RPCException, match=r"Maximum number of trades is reached\."):
rpc._rpc_force_entry(pair, None)
freqtradebot.config["max_open_trades"] = 5
@@ -1286,7 +1286,7 @@ def test_rpc_force_entry_wrong_mode(mocker, default_conf) -> None:
patch_get_signal(freqtradebot)
rpc = RPC(freqtradebot)
pair = "ETH/BTC"
with pytest.raises(RPCException, match="Can't go short on Spot markets."):
with pytest.raises(RPCException, match=r"Can't go short on Spot markets\."):
rpc._rpc_force_entry(pair, None, order_side=SignalDirection.SHORT)

View File

@@ -355,7 +355,7 @@ def test_api__init__(default_conf, mocker):
apiserver = ApiServer(default_conf)
apiserver.add_rpc_handler(RPC(get_patched_freqtradebot(mocker, default_conf)))
assert apiserver._config == default_conf
with pytest.raises(OperationalException, match="RPC Handler already attached."):
with pytest.raises(OperationalException, match=r"RPC Handler already attached\."):
apiserver.add_rpc_handler(RPC(get_patched_freqtradebot(mocker, default_conf)))
apiserver.cleanup()
@@ -534,7 +534,7 @@ def test_api_reloadconf(botclient):
def test_api_pause(botclient):
ftbot, client = botclient
_ftbot, client = botclient
rc = client_post(client, f"{BASE_URI}/pause")
assert_response(rc)
@@ -3281,7 +3281,7 @@ def test_api_download_data(botclient, mocker, tmp_path):
def test_api_markets_live(botclient):
ftbot, client = botclient
_ftbot, client = botclient
rc = client_get(client, f"{BASE_URI}/markets")
assert_response(rc, 200)

View File

@@ -984,7 +984,7 @@ async def test_telegram_profit_long_short_handle(
mocker.patch("freqtrade.rpc.rpc.CryptoToFiatConverter._find_price", return_value=1.1)
mocker.patch.multiple(EXMS, fetch_ticker=ticker_usdt, get_fee=fee)
telegram, freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
telegram, _freqtradebot, msg_mock = get_telegram_testobject(mocker, default_conf_usdt)
# When there are no trades
await telegram._profit_long(update=update, context=MagicMock())

View File

@@ -988,7 +988,7 @@ def test_auto_hyperopt_interface_loadparams(default_conf, mocker, caplog):
}
mocker.patch("freqtrade.strategy.hyper.HyperoptTools.load_params", return_value=expected_result)
with pytest.raises(OperationalException, match="Invalid parameter file provided."):
with pytest.raises(OperationalException, match=r"Invalid parameter file provided\."):
StrategyResolver.load_strategy(default_conf)
mocker.patch(

View File

@@ -111,7 +111,7 @@ def test_load_strategy_noname(default_conf):
default_conf["strategy"] = ""
with pytest.raises(
OperationalException,
match="No strategy set. Please use `--strategy` to specify the strategy class to use.",
match=r"No strategy set. Please use `--strategy` to specify the strategy class to use\.",
):
StrategyResolver.load_strategy(default_conf)

View File

@@ -250,7 +250,7 @@ def test_from_recursive_files(testdatadir) -> None:
assert "test_pricing2_conf.json" in conf["config_files"][3]
files = testdatadir / "testconfigs/recursive.json"
with pytest.raises(OperationalException, match="Config loop detected."):
with pytest.raises(OperationalException, match=r"Config loop detected\."):
load_from_files([files])
@@ -672,7 +672,7 @@ def test_validate_max_open_trades(default_conf):
default_conf["stake_amount"] = "unlimited"
with pytest.raises(
OperationalException,
match="`max_open_trades` and `stake_amount` cannot both be unlimited.",
match=r"`max_open_trades` and `stake_amount` cannot both be unlimited\.",
):
validate_config_consistency(default_conf)
@@ -691,14 +691,15 @@ def test_validate_price_side(default_conf):
conf["order_types"]["entry"] = "market"
with pytest.raises(
OperationalException,
match='Market entry orders require entry_pricing.price_side = "other".',
match=r'Market entry orders require entry_pricing.price_side = "other"\.',
):
validate_config_consistency(conf)
conf = deepcopy(default_conf)
conf["order_types"]["exit"] = "market"
with pytest.raises(
OperationalException, match='Market exit orders require exit_pricing.price_side = "other".'
OperationalException,
match=r'Market exit orders require exit_pricing.price_side = "other"\.',
):
validate_config_consistency(conf)
@@ -716,8 +717,8 @@ def test_validate_tsl(default_conf):
default_conf["stoploss"] = 0.0
with pytest.raises(
OperationalException,
match="The config stoploss needs to be different "
"from 0 to avoid problems with sell orders.",
match=r"The config stoploss needs to be different "
r"from 0 to avoid problems with sell orders\.",
):
validate_config_consistency(default_conf)
default_conf["stoploss"] = -0.10
@@ -767,7 +768,7 @@ def test_validate_whitelist(default_conf):
del conf["exchange"]["pair_whitelist"]
# Test error case
with pytest.raises(
OperationalException, match="StaticPairList requires pair_whitelist to be set."
OperationalException, match=r"StaticPairList requires pair_whitelist to be set\."
):
validate_config_consistency(conf)
@@ -969,7 +970,7 @@ def test__validate_consumers(default_conf, caplog) -> None:
conf = deepcopy(default_conf)
conf.update({"external_message_consumer": {"enabled": True, "producers": []}})
with pytest.raises(
OperationalException, match="You must specify at least 1 Producer to connect to."
OperationalException, match=r"You must specify at least 1 Producer to connect to\."
):
validate_config_consistency(conf)
@@ -996,7 +997,7 @@ def test__validate_consumers(default_conf, caplog) -> None:
}
)
with pytest.raises(
OperationalException, match="Producer names must be unique. Duplicate: default"
OperationalException, match=r"Producer names must be unique\. Duplicate: default"
):
validate_config_consistency(conf)
@@ -1026,7 +1027,7 @@ def test__validate_orderflow(default_conf) -> None:
conf["exchange"]["use_public_trades"] = True
with pytest.raises(
ConfigurationError,
match="Orderflow is a required configuration key when using public trades.",
match=r"Orderflow is a required configuration key when using public trades\.",
):
validate_config_consistency(conf)
@@ -1050,7 +1051,7 @@ def test_validate_edge_removal(default_conf):
}
with pytest.raises(
ConfigurationError,
match="Edge is no longer supported and has been removed from Freqtrade with 2025.6.",
match=r"Edge is no longer supported and has been removed from Freqtrade with 2025\.6\.",
):
validate_config_consistency(default_conf)