Require prefix for environment variables used within config
This commit is contained in:
parent
3df58936b5
commit
a4a72680e0
@ -17,15 +17,17 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
CONFIG_PARSE_MODE = rapidjson.PM_COMMENTS | rapidjson.PM_TRAILING_COMMAS
|
||||
|
||||
ENV_PREFIX = 'FREQTRADE_'
|
||||
|
||||
|
||||
class SubstitutionException(Exception):
|
||||
"""
|
||||
Indicates that a variable within the configuration couldn't be substituted.
|
||||
"""
|
||||
|
||||
def __init__(self, key: str, offset: int):
|
||||
def __init__(self, err: str, offset: int):
|
||||
self.offset = offset
|
||||
self.err = f'Environment variable {key} was requested for substitution, but is not set.'
|
||||
self.err = err
|
||||
super().__init__(self.err)
|
||||
|
||||
|
||||
@ -52,8 +54,17 @@ def substitute_environment_variable(match: re.Match) -> str:
|
||||
Substitutes a matched environment variable with its value
|
||||
"""
|
||||
key = match.group(1).strip()
|
||||
if not key.startswith(ENV_PREFIX):
|
||||
raise SubstitutionException(
|
||||
f'Environment variable {key} must be prefixed with {ENV_PREFIX} .',
|
||||
match.start(0)
|
||||
)
|
||||
|
||||
if key not in environ:
|
||||
raise SubstitutionException(key, match.start(0))
|
||||
raise SubstitutionException(
|
||||
f'Environment variable {key} was requested for substitution, but is not set.',
|
||||
match.start(0)
|
||||
)
|
||||
|
||||
return environ[key]
|
||||
|
||||
|
@ -106,8 +106,8 @@
|
||||
// We can now comment out some settings
|
||||
// "enabled": true,
|
||||
"enabled": false,
|
||||
"token": "${TELEGRAM_TOKEN}",
|
||||
"chat_id": "${TELEGRAM_CHAT}"
|
||||
"token": "${FREQTRADE_TELEGRAM_TOKEN}",
|
||||
"chat_id": "${FREQTRADE_TELEGRAM_CHAT}"
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
|
127
tests/config_test_environment_invalid.json
Normal file
127
tests/config_test_environment_invalid.json
Normal file
@ -0,0 +1,127 @@
|
||||
{
|
||||
/* Single-line C-style comment */
|
||||
"max_open_trades": 3,
|
||||
/*
|
||||
* Multi-line C-style comment
|
||||
*/
|
||||
"stake_currency": "BTC",
|
||||
"stake_amount": 0.05,
|
||||
"fiat_display_currency": "USD", // C++-style comment
|
||||
"amount_reserve_percent" : 0.05, // And more, tabs before this comment
|
||||
"dry_run": false,
|
||||
"timeframe": "5m",
|
||||
"trailing_stop": false,
|
||||
"trailing_stop_positive": 0.005,
|
||||
"trailing_stop_positive_offset": 0.0051,
|
||||
"trailing_only_offset_is_reached": false,
|
||||
"minimal_roi": {
|
||||
"40": 0.0,
|
||||
"30": 0.01,
|
||||
"20": 0.02,
|
||||
"0": 0.04
|
||||
},
|
||||
"stoploss": -0.10,
|
||||
"unfilledtimeout": {
|
||||
"buy": 10,
|
||||
"sell": 30, // Trailing comma should also be accepted now
|
||||
},
|
||||
"bid_strategy": {
|
||||
"use_order_book": false,
|
||||
"ask_last_balance": 0.0,
|
||||
"order_book_top": 1,
|
||||
"check_depth_of_market": {
|
||||
"enabled": false,
|
||||
"bids_to_ask_delta": 1
|
||||
}
|
||||
},
|
||||
"ask_strategy":{
|
||||
"use_order_book": false,
|
||||
"order_book_min": 1,
|
||||
"order_book_max": 9
|
||||
},
|
||||
"order_types": {
|
||||
"buy": "limit",
|
||||
"sell": "limit",
|
||||
"stoploss": "market",
|
||||
"stoploss_on_exchange": false,
|
||||
"stoploss_on_exchange_interval": 60
|
||||
},
|
||||
"order_time_in_force": {
|
||||
"buy": "gtc",
|
||||
"sell": "gtc"
|
||||
},
|
||||
"pairlist": {
|
||||
"method": "VolumePairList",
|
||||
"config": {
|
||||
"number_assets": 20,
|
||||
"sort_key": "quoteVolume",
|
||||
"precision_filter": false
|
||||
}
|
||||
},
|
||||
"exchange": {
|
||||
"name": "bittrex",
|
||||
"sandbox": false,
|
||||
"key": "your_exchange_key",
|
||||
"secret": "your_exchange_secret",
|
||||
"password": "",
|
||||
"ccxt_config": {"enableRateLimit": true},
|
||||
"ccxt_async_config": {
|
||||
"enableRateLimit": false,
|
||||
"rateLimit": 500,
|
||||
"aiohttp_trust_env": false
|
||||
},
|
||||
"pair_whitelist": [
|
||||
"ETH/BTC",
|
||||
"LTC/BTC",
|
||||
"ETC/BTC",
|
||||
"DASH/BTC",
|
||||
"ZEC/BTC",
|
||||
"XLM/BTC",
|
||||
"NXT/BTC",
|
||||
"TRX/BTC",
|
||||
"ADA/BTC",
|
||||
"XMR/BTC"
|
||||
],
|
||||
"pair_blacklist": [
|
||||
"DOGE/BTC"
|
||||
],
|
||||
"outdated_offset": 5,
|
||||
"markets_refresh_interval": 60
|
||||
},
|
||||
"edge": {
|
||||
"enabled": false,
|
||||
"process_throttle_secs": 3600,
|
||||
"calculate_since_number_of_days": 7,
|
||||
"allowed_risk": 0.01,
|
||||
"stoploss_range_min": -0.01,
|
||||
"stoploss_range_max": -0.1,
|
||||
"stoploss_range_step": -0.01,
|
||||
"minimum_winrate": 0.60,
|
||||
"minimum_expectancy": 0.20,
|
||||
"min_trade_number": 10,
|
||||
"max_trade_duration_minute": 1440,
|
||||
"remove_pumps": false
|
||||
},
|
||||
"telegram": {
|
||||
// We can now comment out some settings
|
||||
// "enabled": true,
|
||||
"enabled": false,
|
||||
"token": "${TELEGRAM_TOKEN}",
|
||||
"chat_id": "${TELEGRAM_CHAT}"
|
||||
},
|
||||
"api_server": {
|
||||
"enabled": false,
|
||||
"listen_ip_address": "127.0.0.1",
|
||||
"listen_port": 8080,
|
||||
"username": "freqtrader",
|
||||
"password": "SuperSecurePassword"
|
||||
},
|
||||
"db_url": "sqlite:///tradesv3.sqlite",
|
||||
"initial_state": "running",
|
||||
"forcebuy_enable": false,
|
||||
"internals": {
|
||||
"process_throttle_secs": 5
|
||||
},
|
||||
"strategy": "DefaultStrategy",
|
||||
"strategy_path": "user_data/strategies/"
|
||||
}
|
@ -919,7 +919,10 @@ def test_load_config_test_env_variables(mocker) -> None:
|
||||
token = "17264728:eW91dHUuYmUvMDAwYWw3cnUzbXMg"
|
||||
chat_id = "17263827"
|
||||
|
||||
mocker.patch.dict(os.environ, {'TELEGRAM_TOKEN': token, 'TELEGRAM_CHAT': chat_id})
|
||||
mocker.patch.dict(os.environ, {
|
||||
'FREQTRADE_TELEGRAM_TOKEN': token,
|
||||
'FREQTRADE_TELEGRAM_CHAT': chat_id
|
||||
})
|
||||
config_file = Path(__file__).parents[0] / "config_test_environment.json"
|
||||
conf = load_config_file(str(config_file))
|
||||
|
||||
@ -932,9 +935,18 @@ def test_load_config_test_substitution_error() -> None:
|
||||
"""
|
||||
Load config with environment variables without setting them
|
||||
"""
|
||||
|
||||
config_file = Path(__file__).parents[0] / "config_test_environment.json"
|
||||
with pytest.raises(OperationalException, match=r'.*Environment variable TELEGRAM_TOKEN*'):
|
||||
with pytest.raises(OperationalException, match=r'.*variable FREQTRADE_TELEGRAM_TOKEN*'):
|
||||
load_config_file(str(config_file))
|
||||
|
||||
|
||||
def test_load_config_test_prefix_error() -> None:
|
||||
"""
|
||||
Load config with environment variables without setting them
|
||||
"""
|
||||
|
||||
config_file = Path(__file__).parents[0] / "config_test_environment_invalid.json"
|
||||
with pytest.raises(OperationalException, match=r'.*must be prefixed*'):
|
||||
load_config_file(str(config_file))
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user