Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,11 @@
# v37.0.1

Kubernetes API Version: v1.37.1

- Fixed type checkers such as pyright reporting documented functions and classes in `kubernetes.config`, `kubernetes.stream`, `kubernetes.utils`, `kubernetes.watch` and their `kubernetes.aio` counterparts, for example `config.load_kube_config` and `utils.create_from_yaml`, as not exported since v37.0.0. Wildcard imports such as `from kubernetes.config import *` no longer import unrelated names like `exists` and `expanduser`.

- Fixed importing API submodules such as `core_v1_api` from the deprecated `kubernetes.client.apis` package, which raised `ImportError` since v37.0.0.

# v37.0.0

Kubernetes API Version: v1.37.1
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -135,7 +135,7 @@ supported versions of Kubernetes clusters.
- [client 34.y.z](https://pypi.org/project/kubernetes/34.1.0/): Kubernetes 1.33 or below (+-), Kubernetes 1.34 (✓), Kubernetes 1.35 or above (+-)
- [client 35.y.z](https://pypi.org/project/kubernetes/35.0.0/): Kubernetes 1.34 or below (+-), Kubernetes 1.35 (✓), Kubernetes 1.36 or above (+-)
- [client 36.y.z](https://pypi.org/project/kubernetes/36.0.3/): Kubernetes 1.35 or below (+-), Kubernetes 1.36 (✓), Kubernetes 1.37 or above (+-)
- [client 37.y.z](https://pypi.org/project/kubernetes/37.0.0/): Kubernetes 1.36 or below (+-), Kubernetes 1.37 (✓), Kubernetes 1.38 or above (+-)
- [client 37.y.z](https://pypi.org/project/kubernetes/37.0.1/): Kubernetes 1.36 or below (+-), Kubernetes 1.37 (✓), Kubernetes 1.38 or above (+-)


> See [here](#homogenizing-the-kubernetes-python-client-versions) for an explanation of why there is no v13-v16 release.
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ No description provided (generated by Openapi Generator https://github.com/opena
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:

- API version: release-1.37
- Package version: 37.0.0
- Package version: 37.0.1
- Generator version: 7.25.0
- Build package: org.openapitools.codegen.languages.PythonClientCodegen

Expand Down
2 changes: 1 addition & 1 deletion kubernetes/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

__project__ = 'kubernetes'
# The version is auto-updated. Please do not edit.
__version__ = "37.0.0"
__version__ = "37.0.1"

from . import client
from . import config
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/aio/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ No description provided (generated by Openapi Generator https://github.com/opena
This Python package is automatically generated by the [OpenAPI Generator](https://openapi-generator.tech) project:

- API version: release-1.37
- Package version: 37.0.0
- Package version: 37.0.1
- Generator version: 7.25.0
- Build package: org.openapitools.codegen.languages.PythonClientCodegen

Expand Down
2 changes: 1 addition & 1 deletion kubernetes/aio/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

__project__ = "kubernetes_aio"
# The version is auto-updated. Please do not edit.
__version__ = "37.0.0"
__version__ = "37.0.1"

import kubernetes.aio.client as client
import kubernetes.aio.config as config
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/aio/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
""" # noqa: E501


__version__ = "37.0.0"
__version__ = "37.0.1"

# Define package exports
__all__ = [
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/aio/client/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,7 @@ def __init__(
self.default_headers[header_name] = header_value
self.cookie = cookie
# Set default User-Agent.
self.user_agent = 'OpenAPI-Generator/37.0.0/python'
self.user_agent = 'OpenAPI-Generator/37.0.1/python'
self.client_side_validation = configuration.client_side_validation

async def __aenter__(self):
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/aio/client/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -612,7 +612,7 @@ def to_debug_report(self) -> str:
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: release-1.37\n"\
"SDK Package Version: 37.0.0".\
"SDK Package Version: 37.0.1".\
format(env=sys.platform, pyversion=sys.version)

def get_host_settings(self) -> List[HostSetting]:
Expand Down
13 changes: 13 additions & 0 deletions kubernetes/aio/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,19 @@
new_client_from_config_dict, refresh_token,
)

__all__ = [
"ConfigException",
"load_incluster_config",
"KUBE_CONFIG_DEFAULT_LOCATION",
"list_kube_config_contexts",
"load_kube_config",
"load_kube_config_from_dict",
"new_client_from_config",
"new_client_from_config_dict",
"refresh_token",
"load_config",
]


async def load_config(**kwargs):
"""
Expand Down
4 changes: 4 additions & 0 deletions kubernetes/aio/stream/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
# limitations under the License.

from .ws_client import WsApiClient

__all__ = [
"WsApiClient",
]
20 changes: 20 additions & 0 deletions kubernetes/aio/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,23 @@
is_conflict, is_retry_after_response,
is_too_many_requests, retry_after_backoff,
retry_after_max_retries, retry_after_seconds)

__all__ = [
"FailToCreateError",
"create_from_dict",
"create_from_yaml",
"create_from_yaml_single_item",
"Backoff",
"DEFAULT_BACKOFF",
"DEFAULT_RETRY",
"DEFAULT_RETRY_AFTER_BACKOFF",
"on_error",
"on_retry_after_error",
"retry_on_conflict",
"is_conflict",
"is_retry_after_response",
"is_too_many_requests",
"retry_after_backoff",
"retry_after_max_retries",
"retry_after_seconds",
]
4 changes: 4 additions & 0 deletions kubernetes/aio/watch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
# limitations under the License.

from .watch import Watch

__all__ = [
"Watch",
]
2 changes: 1 addition & 1 deletion kubernetes/client/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
""" # noqa: E501


__version__ = "37.0.0"
__version__ = "37.0.1"

# Define package exports
__all__ = [
Expand Down
2 changes: 1 addition & 1 deletion kubernetes/client/api_client.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def __init__(
self.pool_threads = pool_threads
self._pool_lock = Lock()
# Set default User-Agent.
self.user_agent = 'OpenAPI-Generator/37.0.0/python'
self.user_agent = 'OpenAPI-Generator/37.0.1/python'
self.client_side_validation = configuration.client_side_validation

def close(self):
Expand Down
17 changes: 17 additions & 0 deletions kubernetes/client/apis/__init__.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
from __future__ import absolute_import
from importlib import import_module as _import_module
from types import ModuleType as _ModuleType
import warnings

# flake8: noqa
Expand All @@ -11,3 +13,18 @@
"The package kubernetes.client.apis is renamed and deprecated, use kubernetes.client.api instead (please note that the trailing s was removed).",
DeprecationWarning
)


def __getattr__(name: str) -> _ModuleType:
# kubernetes.client.api imports its submodules lazily, so the star import
# above no longer brings in module names such as core_v1_api.
if name.startswith('_') or not name.isidentifier():
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")
module_name = f"kubernetes.client.api.{name}"
try:
return _import_module(module_name)
except ModuleNotFoundError as e:
if e.name != module_name:
raise
raise AttributeError(
f"module {__name__!r} has no attribute {name!r}") from None
2 changes: 1 addition & 1 deletion kubernetes/client/configuration.py
Original file line number Diff line number Diff line change
Expand Up @@ -613,7 +613,7 @@ def to_debug_report(self) -> str:
"OS: {env}\n"\
"Python Version: {pyversion}\n"\
"Version of the API: release-1.37\n"\
"SDK Package Version: 37.0.0".\
"SDK Package Version: 37.0.1".\
format(env=sys.platform, pyversion=sys.version)

def get_host_settings(self) -> List[HostSetting]:
Expand Down
12 changes: 12 additions & 0 deletions kubernetes/config/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,18 @@
list_kube_config_contexts, load_kube_config,
load_kube_config_from_dict, new_client_from_config, new_client_from_config_dict)

__all__ = [
"ConfigException",
"load_incluster_config",
"KUBE_CONFIG_DEFAULT_LOCATION",
"list_kube_config_contexts",
"load_kube_config",
"load_kube_config_from_dict",
"new_client_from_config",
"new_client_from_config_dict",
"load_config",
]


def load_config(**kwargs):
"""
Expand Down
5 changes: 5 additions & 0 deletions kubernetes/stream/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,8 @@
# limitations under the License.

from .stream import stream, portforward

__all__ = [
"stream",
"portforward",
]
81 changes: 81 additions & 0 deletions kubernetes/test/test_apis_alias.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
# Copyright 2026 The Kubernetes Authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

import importlib
import pkgutil
import unittest
from unittest import mock
import warnings

import kubernetes.client.api


def _import_alias():
# The alias installs its own 'default' filter for its DeprecationWarning,
# so record the warning instead of trying to filter it out.
with warnings.catch_warnings(record=True):
return importlib.import_module('kubernetes.client.apis')


class TestApisAlias(unittest.TestCase):
@classmethod
def setUpClass(cls):
cls.apis = _import_alias()

def test_from_import_submodule(self):
from kubernetes.client.apis import core_v1_api

self.assertIs(
core_v1_api,
importlib.import_module('kubernetes.client.api.core_v1_api'))

def test_every_api_submodule_is_reachable(self):
names = [m.name for m in pkgutil.iter_modules(
kubernetes.client.api.__path__)]
self.assertIn('core_v1_api', names)
for name in names:
with self.subTest(name=name):
self.assertIs(
getattr(self.apis, name),
importlib.import_module('kubernetes.client.api.' + name))

def test_from_import_class(self):
from kubernetes.client.apis import CoreV1Api

self.assertIs(CoreV1Api, kubernetes.client.api.CoreV1Api)

def test_unknown_name(self):
with self.assertRaises(ImportError):
from kubernetes.client.apis import no_such_api # noqa: F401
self.assertFalse(hasattr(self.apis, 'no_such_api'))

def test_non_submodule_names_are_not_imported(self):
with mock.patch('kubernetes.client.apis._import_module') as m:
for name in ('__wrapped__', '_no_such_api', '.core_v1_api'):
with self.subTest(name=name):
self.assertFalse(hasattr(self.apis, name))
m.assert_not_called()

def test_missing_dependency_propagates(self):
error = ModuleNotFoundError("No module named 'missing_dep'",
name='missing_dep')
with mock.patch('kubernetes.client.apis._import_module',
side_effect=error):
with self.assertRaises(ModuleNotFoundError) as cm:
self.apis.core_v1_api
self.assertIs(cm.exception, error)


if __name__ == '__main__':
unittest.main()
26 changes: 26 additions & 0 deletions kubernetes/utils/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,3 +26,29 @@
retry_after_max_retries, retry_on_conflict,
retry_after_seconds)
from .keepalive import tcp_keepalive_socket_options

__all__ = [
"FailToCreateError",
"create_from_dict",
"create_from_yaml",
"create_from_directory",
"parse_quantity",
"parse_duration",
"get_nodes_metrics",
"get_pods_metrics",
"get_pods_metrics_in_all_namespaces",
"Backoff",
"DEFAULT_BACKOFF",
"DEFAULT_RETRY",
"DEFAULT_RETRY_AFTER_BACKOFF",
"is_conflict",
"is_retry_after_response",
"is_too_many_requests",
"on_error",
"on_retry_after_error",
"retry_after_backoff",
"retry_after_max_retries",
"retry_on_conflict",
"retry_after_seconds",
"tcp_keepalive_socket_options",
]
4 changes: 4 additions & 0 deletions kubernetes/watch/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,3 +13,7 @@
# limitations under the License.

from .watch import Watch

__all__ = [
"Watch",
]
2 changes: 1 addition & 1 deletion scripts/constants.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
KUBERNETES_BRANCH = "release-1.37"

# client version for packaging and releasing.
CLIENT_VERSION = "37.0.0"
CLIENT_VERSION = "37.0.1"

# Name of the release package
PACKAGE_NAME = "kubernetes"
Expand Down
2 changes: 1 addition & 1 deletion setup-asyncio.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Do not edit these constants. They will be updated automatically
# by scripts/update-client-asyncio.sh.
CLIENT_VERSION = "37.0.0"
CLIENT_VERSION = "37.0.1"
PACKAGE_NAME = "kubernetes.aio"
DEVELOPMENT_STATUS = "5 - Production/Stable"

Expand Down
2 changes: 1 addition & 1 deletion setup-release.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Do not edit these constants. They will be updated automatically
# by scripts/update-client.sh.
CLIENT_VERSION = "37.0.0"
CLIENT_VERSION = "37.0.1"
PACKAGE_NAME = "kubernetes"
DEVELOPMENT_STATUS = "5 - Production/Stable"

Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@

# Do not edit these constants. They will be updated automatically
# by scripts/update-client.sh.
CLIENT_VERSION = "37.0.0"
CLIENT_VERSION = "37.0.1"
PACKAGE_NAME = "kubernetes"
DEVELOPMENT_STATUS = "5 - Production/Stable"

Expand Down
Loading