Skip to content

Commit 8f6287c

Browse files
Merge pull request #527 from RedHatQE/lessblue
Defer import of system modules and Azure SDKs
2 parents 0f454b3 + 7d61d5d commit 8f6287c

5 files changed

Lines changed: 181 additions & 47 deletions

File tree

.pre-commit-config.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ ci:
33
repos:
44
- repo: https://github.com/astral-sh/ruff-pre-commit
55
# Ruff version.
6-
rev: v0.14.2
6+
rev: v0.15.0
77
hooks:
88
# Run the linter.
99
- id: ruff
@@ -24,7 +24,7 @@ repos:
2424
- id: end-of-file-fixer
2525
- id: debug-statements
2626
- repo: https://github.com/asottile/pyupgrade
27-
rev: v3.21.0
27+
rev: v3.21.2
2828
hooks:
2929
- id: pyupgrade
3030
args: [--py3-plus, --py311-plus]

wrapanapi/__init__.py

Lines changed: 65 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,5 @@
11
# Imports for convenience
22
from .entities.vm import VmState
3-
from .systems.container.podman import Podman
4-
from .systems.container.rhopenshift import Openshift
5-
from .systems.ec2 import EC2System
6-
from .systems.google import GoogleCloudSystem
7-
from .systems.hawkular import HawkularSystem
8-
from .systems.lenovo import LenovoSystem
9-
from .systems.msazure import AzureSystem
10-
from .systems.nuage import NuageSystem
11-
from .systems.openstack import OpenstackSystem
12-
from .systems.openstack_infra import OpenstackInfraSystem
13-
from .systems.redfish import RedfishSystem
14-
from .systems.rhevm import RHEVMSystem
15-
from .systems.scvmm import SCVMMSystem
16-
from .systems.vcloud import VmwareCloudSystem
17-
from .systems.virtualcenter import VMWareSystem
183

194
__all__ = [
205
"EC2System",
@@ -34,3 +19,68 @@
3419
"Podman",
3520
"VmState",
3621
]
22+
23+
24+
def __getattr__(name):
25+
"""Lazy import system classes to avoid loading dependencies for unused providers."""
26+
if name == "EC2System":
27+
from .systems.ec2 import EC2System
28+
29+
return EC2System
30+
elif name == "GoogleCloudSystem":
31+
from .systems.google import GoogleCloudSystem
32+
33+
return GoogleCloudSystem
34+
elif name == "HawkularSystem":
35+
from .systems.hawkular import HawkularSystem
36+
37+
return HawkularSystem
38+
elif name == "LenovoSystem":
39+
from .systems.lenovo import LenovoSystem
40+
41+
return LenovoSystem
42+
elif name == "AzureSystem":
43+
from .systems.msazure import AzureSystem
44+
45+
return AzureSystem
46+
elif name == "NuageSystem":
47+
from .systems.nuage import NuageSystem
48+
49+
return NuageSystem
50+
elif name == "OpenstackSystem":
51+
from .systems.openstack import OpenstackSystem
52+
53+
return OpenstackSystem
54+
elif name == "OpenstackInfraSystem":
55+
from .systems.openstack_infra import OpenstackInfraSystem
56+
57+
return OpenstackInfraSystem
58+
elif name == "RedfishSystem":
59+
from .systems.redfish import RedfishSystem
60+
61+
return RedfishSystem
62+
elif name == "RHEVMSystem":
63+
from .systems.rhevm import RHEVMSystem
64+
65+
return RHEVMSystem
66+
elif name == "SCVMMSystem":
67+
from .systems.scvmm import SCVMMSystem
68+
69+
return SCVMMSystem
70+
elif name == "VmwareCloudSystem":
71+
from .systems.vcloud import VmwareCloudSystem
72+
73+
return VmwareCloudSystem
74+
elif name == "VMWareSystem":
75+
from .systems.virtualcenter import VMWareSystem
76+
77+
return VMWareSystem
78+
elif name == "Openshift":
79+
from .systems.container.rhopenshift import Openshift
80+
81+
return Openshift
82+
elif name == "Podman":
83+
from .systems.container.podman import Podman
84+
85+
return Podman
86+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

wrapanapi/systems/__init__.py

Lines changed: 57 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,3 @@
1-
from .ec2 import EC2System
2-
from .google import GoogleCloudSystem
3-
from .hawkular import HawkularSystem
4-
from .lenovo import LenovoSystem
5-
from .msazure import AzureSystem
6-
from .nuage import NuageSystem
7-
from .openstack import OpenstackSystem
8-
from .openstack_infra import OpenstackInfraSystem
9-
from .redfish import RedfishSystem
10-
from .rhevm import RHEVMSystem
11-
from .scvmm import SCVMMSystem
12-
from .vcloud import VmwareCloudSystem
13-
from .virtualcenter import VMWareSystem
14-
151
__all__ = [
162
"EC2System",
173
"GoogleCloudSystem",
@@ -27,3 +13,60 @@
2713
"VmwareCloudSystem",
2814
"VMWareSystem",
2915
]
16+
17+
18+
def __getattr__(name):
19+
"""Lazy import system classes to avoid loading dependencies for unused providers."""
20+
if name == "EC2System":
21+
from .ec2 import EC2System
22+
23+
return EC2System
24+
elif name == "GoogleCloudSystem":
25+
from .google import GoogleCloudSystem
26+
27+
return GoogleCloudSystem
28+
elif name == "HawkularSystem":
29+
from .hawkular import HawkularSystem
30+
31+
return HawkularSystem
32+
elif name == "LenovoSystem":
33+
from .lenovo import LenovoSystem
34+
35+
return LenovoSystem
36+
elif name == "AzureSystem":
37+
from .msazure import AzureSystem
38+
39+
return AzureSystem
40+
elif name == "NuageSystem":
41+
from .nuage import NuageSystem
42+
43+
return NuageSystem
44+
elif name == "OpenstackSystem":
45+
from .openstack import OpenstackSystem
46+
47+
return OpenstackSystem
48+
elif name == "OpenstackInfraSystem":
49+
from .openstack_infra import OpenstackInfraSystem
50+
51+
return OpenstackInfraSystem
52+
elif name == "RedfishSystem":
53+
from .redfish import RedfishSystem
54+
55+
return RedfishSystem
56+
elif name == "RHEVMSystem":
57+
from .rhevm import RHEVMSystem
58+
59+
return RHEVMSystem
60+
elif name == "SCVMMSystem":
61+
from .scvmm import SCVMMSystem
62+
63+
return SCVMMSystem
64+
elif name == "VmwareCloudSystem":
65+
from .vcloud import VmwareCloudSystem
66+
67+
return VmwareCloudSystem
68+
elif name == "VMWareSystem":
69+
from .virtualcenter import VMWareSystem
70+
71+
return VMWareSystem
72+
raise AttributeError(f"module {__name__!r} has no attribute {name!r}")

wrapanapi/systems/msazure.py

Lines changed: 53 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -8,25 +8,63 @@
88
from functools import cached_property
99

1010
import pytz
11-
from azure.core.exceptions import HttpResponseError
12-
from azure.identity import ClientSecretCredential
13-
from azure.mgmt.compute import ComputeManagementClient
14-
from azure.mgmt.iothub import IotHubClient
15-
from azure.mgmt.network import NetworkManagementClient
16-
from azure.mgmt.network.models import NetworkSecurityGroup, SecurityRule
17-
from azure.mgmt.resource.resources import ResourceManagementClient
18-
from azure.mgmt.storage import StorageManagementClient
19-
from azure.mgmt.subscription import SubscriptionClient
20-
from azure.mgmt.subscription.models import SubscriptionState
21-
from azure.storage.blob import BlobServiceClient
2211
from dateutil import parser
23-
from msrestazure.azure_exceptions import CloudError
2412
from wait_for import wait_for
2513

2614
from wrapanapi.entities import Instance, Template, TemplateMixin, VmMixin, VmState
2715
from wrapanapi.exceptions import ImageNotFoundError, MultipleImagesError, VMInstanceNotFound
2816
from wrapanapi.systems.base import System
2917

18+
# Lazy imports for Azure dependencies to avoid import errors when Azure packages
19+
# are not properly installed or when users don't need Azure functionality
20+
_azure_imports_loaded = False
21+
22+
23+
def _ensure_azure_imports():
24+
"""Lazily import Azure dependencies only when needed."""
25+
global _azure_imports_loaded
26+
global HttpResponseError, ClientSecretCredential, ComputeManagementClient
27+
global IotHubClient, NetworkManagementClient, NetworkSecurityGroup, SecurityRule
28+
global ResourceManagementClient, StorageManagementClient, SubscriptionClient
29+
global SubscriptionState, BlobServiceClient, CloudError
30+
31+
if not _azure_imports_loaded:
32+
from azure.core.exceptions import HttpResponseError as _HttpResponseError
33+
from azure.identity import ClientSecretCredential as _ClientSecretCredential
34+
from azure.mgmt.compute import ComputeManagementClient as _ComputeManagementClient
35+
from azure.mgmt.iothub import IotHubClient as _IotHubClient
36+
from azure.mgmt.network import NetworkManagementClient as _NetworkManagementClient
37+
from azure.mgmt.network.models import (
38+
NetworkSecurityGroup as _NetworkSecurityGroup,
39+
)
40+
from azure.mgmt.network.models import (
41+
SecurityRule as _SecurityRule,
42+
)
43+
from azure.mgmt.resource.resources import (
44+
ResourceManagementClient as _ResourceManagementClient,
45+
)
46+
from azure.mgmt.storage import StorageManagementClient as _StorageManagementClient
47+
from azure.mgmt.subscription import SubscriptionClient as _SubscriptionClient
48+
from azure.mgmt.subscription.models import SubscriptionState as _SubscriptionState
49+
from azure.storage.blob import BlobServiceClient as _BlobServiceClient
50+
from msrestazure.azure_exceptions import CloudError as _CloudError
51+
52+
HttpResponseError = _HttpResponseError
53+
ClientSecretCredential = _ClientSecretCredential
54+
ComputeManagementClient = _ComputeManagementClient
55+
IotHubClient = _IotHubClient
56+
NetworkManagementClient = _NetworkManagementClient
57+
NetworkSecurityGroup = _NetworkSecurityGroup
58+
SecurityRule = _SecurityRule
59+
ResourceManagementClient = _ResourceManagementClient
60+
StorageManagementClient = _StorageManagementClient
61+
SubscriptionClient = _SubscriptionClient
62+
SubscriptionState = _SubscriptionState
63+
BlobServiceClient = _BlobServiceClient
64+
CloudError = _CloudError
65+
66+
_azure_imports_loaded = True
67+
3068

3169
class AzureInstance(Instance):
3270
state_map = {
@@ -47,6 +85,7 @@ def __init__(self, system, raw=None, **kwargs):
4785
name: name of instance
4886
resource_group: name of resource group this instance is in
4987
"""
88+
_ensure_azure_imports()
5089
self._resource_group = kwargs.get("resource_group")
5190
self._name = kwargs.get("name")
5291
if not self._name or not self._resource_group:
@@ -304,6 +343,7 @@ def __init__(self, system, raw=None, **kwargs):
304343
name: name of template
305344
container: container the template is stored in
306345
"""
346+
_ensure_azure_imports()
307347
self._name = kwargs.get("name")
308348
self._container = kwargs.get("container")
309349
if not self._name or not self._container:
@@ -488,6 +528,7 @@ class AzureSystem(System, VmMixin, TemplateMixin):
488528
}
489529

490530
def __init__(self, **kwargs):
531+
_ensure_azure_imports()
491532
super().__init__(**kwargs)
492533
self.client_id = kwargs.get("username")
493534
self.client_secret = kwargs.get("password")

wrapanapi/systems/nuage.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -22,10 +22,10 @@ class NuageSystem(System):
2222
# entities.count() == (fetcher, served object, count of fetched objects)
2323
"num_security_group": lambda self: self.api.policy_groups.count()[2],
2424
# Filter out 'BackHaulSubnet' and combine it with l2_domains the same way CloudForms does
25-
"num_cloud_subnet": lambda self: self.api.subnets.count(filter="name != 'BackHaulSubnet'")[
26-
2
27-
]
28-
+ self.api.l2_domains.count()[2],
25+
"num_cloud_subnet": lambda self: (
26+
self.api.subnets.count(filter="name != 'BackHaulSubnet'")[2]
27+
+ self.api.l2_domains.count()[2]
28+
),
2929
"num_cloud_tenant": lambda self: self.api.enterprises.count()[2],
3030
"num_network_router": lambda self: self.api.domains.count()[2],
3131
"num_cloud_network": lambda self: len(self.list_floating_network_resources()),

0 commit comments

Comments
 (0)