Invalid POETRY_REQUESTS_TIMEOUT can fail at import time instead of using config normalization
Summary
Setting POETRY_REQUESTS_TIMEOUT to a non-integer value can make even unrelated commands such as poetry --version fail during import with a raw ValueError traceback.
Reproduction
POETRY_REQUESTS_TIMEOUT=abc python -m poetry --versionActual behavior
The process fails during import with a traceback ending in:
ValueError: invalid literal for int() with base 10: 'abc'The failing line is the import-time conversion of the environment variable:
REQUESTS_TIMEOUT = int(os.getenv("POETRY_REQUESTS_TIMEOUT", 15))Expected behavior
Invalid POETRY_REQUESTS_TIMEOUT values should ideally be reported as a Poetry configuration error that names the variable and expected type, rather than as an import-time traceback. Also, commands that do not use HTTP requests, such as poetry --version, probably should not fail because an HTTP timeout environment variable is malformed.
If the intended product semantics are that malformed environment variables are allowed to fail at import time, it would be helpful to state that explicitly. Otherwise, this looks inconsistent with Poetry's existing typed configuration normalization path.
Why int_normalizer makes this look inconsistent
Poetry already has a configuration normalization mechanism for environment-derived settings. In Config.get, environment variables are looked up and passed through the appropriate normalizer:
env = "POETRY_" + "_".join(k.upper().replace("-", "_") for k in keys)
env_value = os.getenv(env)
if env_value is not None:
return self.process(self._get_normalizer(setting_name)(env_value))For integer settings, Poetry explicitly uses int_normalizer:
@staticmethod
def _get_normalizer(name: str) -> Callable[[str], Any]:
if name in {
"installer.max-workers",
"requests.max-retries",
"solver.lazy-wheel",
}:
return int_normalizerThat means config-backed integer values already have a single typed conversion point. POETRY_REQUESTS_TIMEOUT, however, bypasses this path and is converted directly in poetry.utils.constants at import time:
REQUESTS_TIMEOUT = int(os.getenv("POETRY_REQUESTS_TIMEOUT", 15))The parsed value is later consumed as an HTTP timeout, for example by request/authenticator code. The contract drift is that this timeout behaves like a typed numeric configuration, but it does not use the existing typed configuration normalizer and therefore fails with a raw import-time ValueError.
Possible fixes
A few possible directions:
- Move this setting into Poetry's normal config path and use the existing integer normalization mechanism.
- Delay parsing until the timeout is actually needed by HTTP code.
- Catch
ValueErrorand raise a Poetry-facing configuration error such asPOETRY_REQUESTS_TIMEOUT must be an integer number of seconds.
A regression test could set POETRY_REQUESTS_TIMEOUT=abc and assert that startup does not produce a raw traceback, especially for commands that do not perform HTTP requests.
Submitted with PilotDeck (OpenBMB/PilotDeck).
Source: python-poetry/poetry