diff --git a/modules/openapi-generator/src/main/resources/python/configuration.mustache b/modules/openapi-generator/src/main/resources/python/configuration.mustache index 7019fa6c7dd2..81d1d8da60d9 100644 --- a/modules/openapi-generator/src/main/resources/python/configuration.mustache +++ b/modules/openapi-generator/src/main/resources/python/configuration.mustache @@ -495,21 +495,24 @@ conf = {{{packageName}}}.Configuration( {{^async}} # urllib3 does not read proxy environment variables itself: # https://github.com/urllib3/urllib3/issues/1785 + # A proxy taken from the environment is re-resolved when the host is + # assigned; see the host setter. + self._proxy_from_env = proxy is None if proxy is None or no_proxy is None: proxies = getproxies() if proxy is None: - scheme = urlparse(self.host).scheme - proxy = proxies.get(scheme) or proxies.get("all") + proxy = self._env_proxy(proxies, self.host) if no_proxy is None: no_proxy = proxies.get("no") + self._proxy = proxy + self.no_proxy = no_proxy + """Hosts that bypass the proxy + """ {{/async}} +{{#async}} self.proxy = proxy """Proxy URL """ -{{^async}} - self.no_proxy = no_proxy - """Hosts that bypass the proxy - """ {{/async}} self.proxy_headers = proxy_headers """Proxy headers @@ -991,3 +994,25 @@ conf = {{{packageName}}}.Configuration( """Fix base path.""" self._base_path = value self.server_index = None +{{^async}} + if self._proxy_from_env: + # the scheme-specific proxy depends on the host, which is + # commonly assigned after construction + self._proxy = self._env_proxy(getproxies(), value) + + @staticmethod + def _env_proxy(proxies: Dict[str, str], host: str) -> Optional[str]: + """Pick the environment proxy that applies to `host`.""" + return proxies.get(urlparse(host).scheme) or proxies.get("all") + + @property + def proxy(self) -> Optional[str]: + """Proxy URL + """ + return self._proxy + + @proxy.setter + def proxy(self, value: Optional[str]) -> None: + self._proxy = value + self._proxy_from_env = False +{{/async}} diff --git a/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py b/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py index 2bbf005e307a..f2411fe6bd9d 100644 --- a/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py +++ b/samples/client/echo_api/python-disallowAdditionalPropertiesIfNotPresent/openapi_client/configuration.py @@ -337,16 +337,16 @@ def __init__( # urllib3 does not read proxy environment variables itself: # https://github.com/urllib3/urllib3/issues/1785 + # A proxy taken from the environment is re-resolved when the host is + # assigned; see the host setter. + self._proxy_from_env = proxy is None if proxy is None or no_proxy is None: proxies = getproxies() if proxy is None: - scheme = urlparse(self.host).scheme - proxy = proxies.get(scheme) or proxies.get("all") + proxy = self._env_proxy(proxies, self.host) if no_proxy is None: no_proxy = proxies.get("no") - self.proxy = proxy - """Proxy URL - """ + self._proxy = proxy self.no_proxy = no_proxy """Hosts that bypass the proxy """ @@ -657,3 +657,23 @@ def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None + if self._proxy_from_env: + # the scheme-specific proxy depends on the host, which is + # commonly assigned after construction + self._proxy = self._env_proxy(getproxies(), value) + + @staticmethod + def _env_proxy(proxies: Dict[str, str], host: str) -> Optional[str]: + """Pick the environment proxy that applies to `host`.""" + return proxies.get(urlparse(host).scheme) or proxies.get("all") + + @property + def proxy(self) -> Optional[str]: + """Proxy URL + """ + return self._proxy + + @proxy.setter + def proxy(self, value: Optional[str]) -> None: + self._proxy = value + self._proxy_from_env = False diff --git a/samples/client/echo_api/python/openapi_client/configuration.py b/samples/client/echo_api/python/openapi_client/configuration.py index 2bbf005e307a..f2411fe6bd9d 100644 --- a/samples/client/echo_api/python/openapi_client/configuration.py +++ b/samples/client/echo_api/python/openapi_client/configuration.py @@ -337,16 +337,16 @@ def __init__( # urllib3 does not read proxy environment variables itself: # https://github.com/urllib3/urllib3/issues/1785 + # A proxy taken from the environment is re-resolved when the host is + # assigned; see the host setter. + self._proxy_from_env = proxy is None if proxy is None or no_proxy is None: proxies = getproxies() if proxy is None: - scheme = urlparse(self.host).scheme - proxy = proxies.get(scheme) or proxies.get("all") + proxy = self._env_proxy(proxies, self.host) if no_proxy is None: no_proxy = proxies.get("no") - self.proxy = proxy - """Proxy URL - """ + self._proxy = proxy self.no_proxy = no_proxy """Hosts that bypass the proxy """ @@ -657,3 +657,23 @@ def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None + if self._proxy_from_env: + # the scheme-specific proxy depends on the host, which is + # commonly assigned after construction + self._proxy = self._env_proxy(getproxies(), value) + + @staticmethod + def _env_proxy(proxies: Dict[str, str], host: str) -> Optional[str]: + """Pick the environment proxy that applies to `host`.""" + return proxies.get(urlparse(host).scheme) or proxies.get("all") + + @property + def proxy(self) -> Optional[str]: + """Proxy URL + """ + return self._proxy + + @proxy.setter + def proxy(self, value: Optional[str]) -> None: + self._proxy = value + self._proxy_from_env = False diff --git a/samples/client/others/python-legacy-model-dictionaries/legacy_model_dict_client/configuration.py b/samples/client/others/python-legacy-model-dictionaries/legacy_model_dict_client/configuration.py index 8e689e45eb90..b99862654f04 100644 --- a/samples/client/others/python-legacy-model-dictionaries/legacy_model_dict_client/configuration.py +++ b/samples/client/others/python-legacy-model-dictionaries/legacy_model_dict_client/configuration.py @@ -317,16 +317,16 @@ def __init__( # urllib3 does not read proxy environment variables itself: # https://github.com/urllib3/urllib3/issues/1785 + # A proxy taken from the environment is re-resolved when the host is + # assigned; see the host setter. + self._proxy_from_env = proxy is None if proxy is None or no_proxy is None: proxies = getproxies() if proxy is None: - scheme = urlparse(self.host).scheme - proxy = proxies.get(scheme) or proxies.get("all") + proxy = self._env_proxy(proxies, self.host) if no_proxy is None: no_proxy = proxies.get("no") - self.proxy = proxy - """Proxy URL - """ + self._proxy = proxy self.no_proxy = no_proxy """Hosts that bypass the proxy """ @@ -623,3 +623,23 @@ def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None + if self._proxy_from_env: + # the scheme-specific proxy depends on the host, which is + # commonly assigned after construction + self._proxy = self._env_proxy(getproxies(), value) + + @staticmethod + def _env_proxy(proxies: Dict[str, str], host: str) -> Optional[str]: + """Pick the environment proxy that applies to `host`.""" + return proxies.get(urlparse(host).scheme) or proxies.get("all") + + @property + def proxy(self) -> Optional[str]: + """Proxy URL + """ + return self._proxy + + @proxy.setter + def proxy(self, value: Optional[str]) -> None: + self._proxy = value + self._proxy_from_env = False diff --git a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py index 8f0b80ef4aed..7e9c9d177921 100644 --- a/samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py +++ b/samples/openapi3/client/petstore/python-lazyImports/petstore_api/configuration.py @@ -407,16 +407,16 @@ def __init__( # urllib3 does not read proxy environment variables itself: # https://github.com/urllib3/urllib3/issues/1785 + # A proxy taken from the environment is re-resolved when the host is + # assigned; see the host setter. + self._proxy_from_env = proxy is None if proxy is None or no_proxy is None: proxies = getproxies() if proxy is None: - scheme = urlparse(self.host).scheme - proxy = proxies.get(scheme) or proxies.get("all") + proxy = self._env_proxy(proxies, self.host) if no_proxy is None: no_proxy = proxies.get("no") - self.proxy = proxy - """Proxy URL - """ + self._proxy = proxy self.no_proxy = no_proxy """Hosts that bypass the proxy """ @@ -805,3 +805,23 @@ def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None + if self._proxy_from_env: + # the scheme-specific proxy depends on the host, which is + # commonly assigned after construction + self._proxy = self._env_proxy(getproxies(), value) + + @staticmethod + def _env_proxy(proxies: Dict[str, str], host: str) -> Optional[str]: + """Pick the environment proxy that applies to `host`.""" + return proxies.get(urlparse(host).scheme) or proxies.get("all") + + @property + def proxy(self) -> Optional[str]: + """Proxy URL + """ + return self._proxy + + @proxy.setter + def proxy(self, value: Optional[str]) -> None: + self._proxy = value + self._proxy_from_env = False diff --git a/samples/openapi3/client/petstore/python/petstore_api/configuration.py b/samples/openapi3/client/petstore/python/petstore_api/configuration.py index fcbc987747b6..3fdb5641b4d3 100755 --- a/samples/openapi3/client/petstore/python/petstore_api/configuration.py +++ b/samples/openapi3/client/petstore/python/petstore_api/configuration.py @@ -407,16 +407,16 @@ def __init__( # urllib3 does not read proxy environment variables itself: # https://github.com/urllib3/urllib3/issues/1785 + # A proxy taken from the environment is re-resolved when the host is + # assigned; see the host setter. + self._proxy_from_env = proxy is None if proxy is None or no_proxy is None: proxies = getproxies() if proxy is None: - scheme = urlparse(self.host).scheme - proxy = proxies.get(scheme) or proxies.get("all") + proxy = self._env_proxy(proxies, self.host) if no_proxy is None: no_proxy = proxies.get("no") - self.proxy = proxy - """Proxy URL - """ + self._proxy = proxy self.no_proxy = no_proxy """Hosts that bypass the proxy """ @@ -801,3 +801,23 @@ def host(self, value: str) -> None: """Fix base path.""" self._base_path = value self.server_index = None + if self._proxy_from_env: + # the scheme-specific proxy depends on the host, which is + # commonly assigned after construction + self._proxy = self._env_proxy(getproxies(), value) + + @staticmethod + def _env_proxy(proxies: Dict[str, str], host: str) -> Optional[str]: + """Pick the environment proxy that applies to `host`.""" + return proxies.get(urlparse(host).scheme) or proxies.get("all") + + @property + def proxy(self) -> Optional[str]: + """Proxy URL + """ + return self._proxy + + @proxy.setter + def proxy(self, value: Optional[str]) -> None: + self._proxy = value + self._proxy_from_env = False diff --git a/samples/openapi3/client/petstore/python/tests/test_configuration.py b/samples/openapi3/client/petstore/python/tests/test_configuration.py index 3dfa32ae4f99..146900e92a5d 100644 --- a/samples/openapi3/client/petstore/python/tests/test_configuration.py +++ b/samples/openapi3/client/petstore/python/tests/test_configuration.py @@ -101,6 +101,68 @@ def test_explicit_proxy_does_not_resolve_generated_host(self): self.assertEqual(config.proxy, "http://proxy.example") + def test_proxy_settings_follow_host_assigned_after_construction(self): + environment_proxies = { + "http": "http://plain-proxy.example", + "https": "http://secure-proxy.example", + } + with patch( + "petstore_api.configuration.getproxies", + return_value=environment_proxies, + ): + config = petstore_api.Configuration() + + config.host = "https://api.example" + self.assertEqual(config.proxy, "http://secure-proxy.example") + + config.host = "http://api.example" + self.assertEqual(config.proxy, "http://plain-proxy.example") + + def test_proxy_settings_resolve_for_a_host_unknown_at_construction(self): + # a spec without a server URL leaves the host empty until the caller + # assigns one, which is when the scheme first becomes known + with patch( + "petstore_api.configuration.getproxies", + return_value={"https": "http://secure-proxy.example"}, + ): + config = petstore_api.Configuration(host="") + self.assertIsNone(config.proxy) + + config.host = "https://api.example" + self.assertEqual(config.proxy, "http://secure-proxy.example") + + def test_assigned_proxy_survives_later_host_assignment(self): + with patch( + "petstore_api.configuration.getproxies", + return_value={"https": "http://secure-proxy.example"}, + ): + config = petstore_api.Configuration() + config.proxy = "http://assigned-proxy.example" + config.host = "https://api.example" + + self.assertEqual(config.proxy, "http://assigned-proxy.example") + + def test_assigned_none_proxy_disables_the_environment(self): + with patch( + "petstore_api.configuration.getproxies", + return_value={"https": "http://secure-proxy.example"}, + ): + config = petstore_api.Configuration() + config.proxy = None + config.host = "https://api.example" + + self.assertIsNone(config.proxy) + + def test_assigned_host_falls_back_to_the_all_proxy(self): + with patch( + "petstore_api.configuration.getproxies", + return_value={"all": "http://any-proxy.example"}, + ): + config = petstore_api.Configuration() + config.host = "https://api.example" + + self.assertEqual(config.proxy, "http://any-proxy.example") + def test_ignore_operation_servers(self): self.config.ignore_operation_servers = True self.assertTrue(self.config.ignore_operation_servers)