qontract-reconcile 0.10.2.dev280__py3-none-any.whl → 0.10.2.dev282__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (72) hide show
  1. {qontract_reconcile-0.10.2.dev280.dist-info → qontract_reconcile-0.10.2.dev282.dist-info}/METADATA +1 -1
  2. {qontract_reconcile-0.10.2.dev280.dist-info → qontract_reconcile-0.10.2.dev282.dist-info}/RECORD +72 -72
  3. reconcile/acs_policies.py +7 -7
  4. reconcile/aus/base.py +1 -1
  5. reconcile/aus/models.py +4 -5
  6. reconcile/aus/version_gate_approver.py +4 -1
  7. reconcile/aws_account_manager/merge_request_manager.py +5 -3
  8. reconcile/aws_ami_cleanup/integration.py +5 -8
  9. reconcile/aws_cloudwatch_log_retention/integration.py +6 -6
  10. reconcile/database_access_manager.py +1 -1
  11. reconcile/deadmanssnitch.py +1 -1
  12. reconcile/dynatrace_token_provider/ocm.py +10 -11
  13. reconcile/fleet_labeler/dependencies.py +7 -3
  14. reconcile/fleet_labeler/ocm.py +6 -4
  15. reconcile/gitlab_housekeeping.py +2 -2
  16. reconcile/gitlab_permissions.py +1 -1
  17. reconcile/jenkins_webhooks.py +8 -4
  18. reconcile/jenkins_worker_fleets.py +2 -2
  19. reconcile/ocm_internal_notifications/integration.py +6 -4
  20. reconcile/ocm_labels/integration.py +7 -7
  21. reconcile/ocm_upgrade_scheduler_org_updater.py +2 -4
  22. reconcile/openshift_cluster_bots.py +1 -1
  23. reconcile/resource_scraper.py +1 -1
  24. reconcile/saas_auto_promotions_manager/integration.py +7 -3
  25. reconcile/saas_auto_promotions_manager/s3_exporter.py +6 -3
  26. reconcile/saas_file_validator.py +1 -2
  27. reconcile/skupper_network/models.py +4 -2
  28. reconcile/statuspage/atlassian.py +1 -1
  29. reconcile/statuspage/page.py +1 -1
  30. reconcile/terraform_cloudflare_resources.py +1 -1
  31. reconcile/terraform_resources.py +1 -1
  32. reconcile/terraform_tgw_attachments.py +3 -3
  33. reconcile/terraform_users.py +1 -1
  34. reconcile/utils/aws_api.py +12 -30
  35. reconcile/utils/aws_api_typed/account.py +4 -4
  36. reconcile/utils/aws_api_typed/api.py +4 -2
  37. reconcile/utils/aws_api_typed/dynamodb.py +2 -2
  38. reconcile/utils/aws_api_typed/iam.py +2 -2
  39. reconcile/utils/aws_api_typed/organization.py +10 -7
  40. reconcile/utils/aws_api_typed/s3.py +2 -3
  41. reconcile/utils/aws_api_typed/service_quotas.py +4 -1
  42. reconcile/utils/aws_api_typed/sts.py +2 -2
  43. reconcile/utils/aws_api_typed/support.py +2 -2
  44. reconcile/utils/dynatrace/client.py +4 -1
  45. reconcile/utils/expiration.py +1 -1
  46. reconcile/utils/external_resource_spec.py +4 -2
  47. reconcile/utils/gitlab_api.py +4 -4
  48. reconcile/utils/glitchtip/models.py +4 -2
  49. reconcile/utils/jira_client.py +4 -4
  50. reconcile/utils/mr/base.py +1 -1
  51. reconcile/utils/oc_connection_parameters.py +4 -1
  52. reconcile/utils/ocm/base.py +4 -1
  53. reconcile/utils/ocm/ocm.py +6 -5
  54. reconcile/utils/ocm/products.py +7 -4
  55. reconcile/utils/saasherder/interfaces.py +5 -2
  56. reconcile/utils/slack_api.py +4 -5
  57. reconcile/utils/state.py +9 -9
  58. reconcile/utils/terraform_client.py +1 -1
  59. reconcile/utils/terrascript_aws_client.py +3 -3
  60. reconcile/utils/vaultsecretref.py +1 -1
  61. reconcile/utils/vcs.py +14 -10
  62. reconcile/vault_replication.py +1 -1
  63. reconcile/vpc_peerings_validator.py +2 -4
  64. tools/app_interface_reporter.py +1 -2
  65. tools/cli_commands/erv2.py +7 -4
  66. tools/cli_commands/gpg_encrypt.py +4 -1
  67. tools/qontract_cli.py +10 -8
  68. tools/saas_metrics_exporter/commit_distance/channel.py +6 -3
  69. tools/saas_metrics_exporter/main.py +4 -1
  70. tools/saas_promotion_state/saas_promotion_state.py +4 -1
  71. {qontract_reconcile-0.10.2.dev280.dist-info → qontract_reconcile-0.10.2.dev282.dist-info}/WHEEL +0 -0
  72. {qontract_reconcile-0.10.2.dev280.dist-info → qontract_reconcile-0.10.2.dev282.dist-info}/entry_points.txt +0 -0
@@ -51,7 +51,7 @@ class DeadMansSnitchIntegration(QontractReconcileIntegration[NoParams]):
51
51
  super().__init__(NoParams())
52
52
  self.qontract_integration_version = make_semver(0, 1, 0)
53
53
  self.settings = get_deadmanssnitch_settings()
54
- self.vault_client = cast(_VaultClient, VaultClient())
54
+ self.vault_client = cast("_VaultClient", VaultClient())
55
55
 
56
56
  @staticmethod
57
57
  def get_snitch_name(cluster: ClusterV1) -> str:
@@ -1,19 +1,13 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Mapping
4
- from datetime import timedelta
5
- from typing import Any
3
+ from typing import TYPE_CHECKING, Any
6
4
 
7
5
  from pydantic import BaseModel
8
6
 
9
- from reconcile.utils.ocm.base import (
10
- OCMClusterServiceLogCreateModel,
11
- )
12
7
  from reconcile.utils.ocm.clusters import (
13
8
  ClusterDetails,
14
9
  discover_clusters_by_labels,
15
10
  )
16
- from reconcile.utils.ocm.labels import Filter
17
11
  from reconcile.utils.ocm.manifests import (
18
12
  create_manifest,
19
13
  get_manifest,
@@ -25,9 +19,14 @@ from reconcile.utils.ocm.syncsets import (
25
19
  get_syncset,
26
20
  patch_syncset,
27
21
  )
28
- from reconcile.utils.ocm_base_client import (
29
- OCMBaseClient,
30
- )
22
+
23
+ if TYPE_CHECKING:
24
+ from collections.abc import Mapping
25
+ from datetime import timedelta
26
+
27
+ from reconcile.utils.ocm.base import OCMClusterServiceLogCreateModel
28
+ from reconcile.utils.ocm.labels import Filter
29
+ from reconcile.utils.ocm_base_client import OCMBaseClient
31
30
 
32
31
  """
33
32
  Thin abstractions of reconcile.ocm module to reduce coupling.
@@ -40,7 +39,7 @@ class OCMCluster(BaseModel):
40
39
  organization_id: str
41
40
  subscription_id: str
42
41
  is_hcp: bool
43
- labels: Mapping[str, str]
42
+ labels: dict[str, str]
44
43
 
45
44
  @staticmethod
46
45
  def from_cluster_details(cluster: ClusterDetails) -> OCMCluster | None:
@@ -1,11 +1,10 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Mapping
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from reconcile.fleet_labeler.metrics import FleetLabelerMetrics
6
6
  from reconcile.fleet_labeler.ocm import OCMClient, OCMClientConfig
7
7
  from reconcile.fleet_labeler.vcs import VCS
8
- from reconcile.gql_definitions.fleet_labeler.fleet_labels import FleetLabelsSpecV1
9
8
  from reconcile.typed_queries.app_interface_repo_url import get_app_interface_repo_url
10
9
  from reconcile.typed_queries.fleet_labels import get_fleet_label_specs
11
10
  from reconcile.typed_queries.github_orgs import get_github_orgs
@@ -13,9 +12,14 @@ from reconcile.typed_queries.gitlab_instances import get_gitlab_instances
13
12
  from reconcile.utils.ocm_base_client import (
14
13
  init_ocm_base_client,
15
14
  )
16
- from reconcile.utils.secret_reader import SecretReaderBase
17
15
  from reconcile.utils.vcs import VCS as VCSBase
18
16
 
17
+ if TYPE_CHECKING:
18
+ from collections.abc import Mapping
19
+
20
+ from reconcile.gql_definitions.fleet_labeler.fleet_labels import FleetLabelsSpecV1
21
+ from reconcile.utils.secret_reader import SecretReaderBase
22
+
19
23
 
20
24
  class Dependencies:
21
25
  """
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Mapping
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from pydantic import BaseModel
6
6
 
@@ -15,9 +15,11 @@ from reconcile.utils.ocm.labels import (
15
15
  update_label,
16
16
  )
17
17
  from reconcile.utils.ocm.search_filters import Filter, FilterMode
18
- from reconcile.utils.ocm_base_client import (
19
- OCMBaseClient,
20
- )
18
+
19
+ if TYPE_CHECKING:
20
+ from collections.abc import Mapping
21
+
22
+ from reconcile.utils.ocm_base_client import OCMBaseClient
21
23
 
22
24
  """
23
25
  Thin abstractions of reconcile.ocm module to reduce coupling.
@@ -343,14 +343,14 @@ def is_good_to_merge(labels: Iterable[str]) -> bool:
343
343
  def is_rebased(mr: ProjectMergeRequest, gl: GitLabApi) -> bool:
344
344
  target_branch = mr.target_branch
345
345
  head = cast(
346
- list[ProjectCommit],
346
+ "list[ProjectCommit]",
347
347
  gl.project.commits.list(
348
348
  ref_name=target_branch,
349
349
  per_page=1,
350
350
  page=1,
351
351
  ),
352
352
  )[0].id
353
- result = cast(dict, gl.project.repository_compare(mr.sha, head))
353
+ result = cast("dict", gl.project.repository_compare(mr.sha, head))
354
354
  return len(result["commits"]) == 0
355
355
 
356
356
 
@@ -56,7 +56,7 @@ class GroupPermissionHandler:
56
56
  # get all projects shared with group
57
57
  shared_projects = self.group.shared_projects.list(iterator=True)
58
58
  current_state = {
59
- project.web_url: self.extract_group_spec(cast(SharedProject, project))
59
+ project.web_url: self.extract_group_spec(cast("SharedProject", project))
60
60
  for project in shared_projects
61
61
  }
62
62
  self.reconcile(desired_state, current_state)
@@ -1,15 +1,19 @@
1
+ from __future__ import annotations
2
+
1
3
  import copy
2
4
  import logging
3
- from collections.abc import Callable, MutableMapping
4
- from typing import Any
5
+ from typing import TYPE_CHECKING, Any
5
6
 
6
7
  from reconcile import queries
7
8
  from reconcile.jenkins_job_builder import init_jjb
8
9
  from reconcile.utils.defer import defer
9
10
  from reconcile.utils.gitlab_api import GitLabApi
10
- from reconcile.utils.jjb_client import JJB
11
11
  from reconcile.utils.secret_reader import SecretReader
12
12
 
13
+ if TYPE_CHECKING:
14
+ from collections.abc import Callable, MutableMapping
15
+
16
+
13
17
  QONTRACT_INTEGRATION = "jenkins-webhooks"
14
18
 
15
19
 
@@ -50,7 +54,7 @@ def get_hooks_to_add(
50
54
  @defer
51
55
  def run(dry_run: bool, defer: Callable | None = None) -> None:
52
56
  secret_reader = SecretReader(queries.get_secret_reader_settings())
53
- jjb: JJB = init_jjb(secret_reader)
57
+ jjb = init_jjb(secret_reader)
54
58
  gl = get_gitlab_api(secret_reader)
55
59
  if defer:
56
60
  defer(gl.cleanup)
@@ -20,8 +20,8 @@ QONTRACT_INTEGRATION = "jenkins-worker-fleets"
20
20
  def get_current_state(jenkins: JenkinsApi) -> list[JenkinsWorkerFleet]:
21
21
  current_state = []
22
22
 
23
- jenkins_config = cast(dict[str, Any], jenkins.get_jcasc_config().get("jenkins"))
24
- clouds = cast(list[dict[str, Any]], jenkins_config.get("clouds", []))
23
+ jenkins_config = cast("dict[str, Any]", jenkins.get_jcasc_config().get("jenkins"))
24
+ clouds = cast("list[dict[str, Any]]", jenkins_config.get("clouds", []))
25
25
  for c in clouds:
26
26
  # eC2Fleet is defined by jcasc schema
27
27
  fleet = c.get("eC2Fleet", None)
@@ -1,15 +1,12 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from collections.abc import (
5
- Callable,
6
- )
7
4
  from functools import lru_cache
5
+ from typing import TYPE_CHECKING
8
6
 
9
7
  from reconcile.gql_definitions.common.ocm_environments import (
10
8
  query as ocm_environment_query,
11
9
  )
12
- from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
13
10
  from reconcile.slack_base import slackapi_from_queries
14
11
  from reconcile.typed_queries.app_interface_custom_messages import (
15
12
  get_app_interface_custom_message,
@@ -25,6 +22,11 @@ from reconcile.utils.runtime.integration import (
25
22
  )
26
23
  from reconcile.utils.slack_api import UserNotFoundError
27
24
 
25
+ if TYPE_CHECKING:
26
+ from collections.abc import Callable
27
+
28
+ from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
29
+
28
30
  QONTRACT_INTEGRATION = "ocm-internal-notifications"
29
31
 
30
32
 
@@ -1,11 +1,7 @@
1
1
  from __future__ import annotations
2
2
 
3
3
  import logging
4
- from collections.abc import (
5
- Callable,
6
- Iterable,
7
- )
8
- from typing import Any
4
+ from typing import TYPE_CHECKING, Any
9
5
 
10
6
  from deepdiff import DeepHash
11
7
  from pydantic import validator
@@ -17,7 +13,6 @@ from reconcile.aus.aus_label_source import (
17
13
  from reconcile.gql_definitions.common.ocm_environments import (
18
14
  query as ocm_environment_query,
19
15
  )
20
- from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
21
16
  from reconcile.gql_definitions.ocm_labels.clusters import ClusterV1
22
17
  from reconcile.gql_definitions.ocm_labels.clusters import query as cluster_query
23
18
  from reconcile.gql_definitions.ocm_labels.organizations import OpenShiftClusterManagerV1
@@ -53,7 +48,12 @@ from reconcile.utils.runtime.integration import (
53
48
  PydanticRunParams,
54
49
  QontractReconcileIntegration,
55
50
  )
56
- from reconcile.utils.secret_reader import SecretReaderBase
51
+
52
+ if TYPE_CHECKING:
53
+ from collections.abc import Callable, Iterable
54
+
55
+ from reconcile.gql_definitions.fragments.ocm_environment import OCMEnvironment
56
+ from reconcile.utils.secret_reader import SecretReaderBase
57
57
 
58
58
  QONTRACT_INTEGRATION = "ocm-labels"
59
59
 
@@ -10,11 +10,9 @@ from reconcile import (
10
10
  mr_client_gateway,
11
11
  queries,
12
12
  )
13
+ from reconcile.ocm.types import OCMSpec
13
14
  from reconcile.utils.jinja2.utils import process_jinja2_template
14
- from reconcile.utils.ocm import (
15
- OCMMap,
16
- OCMSpec,
17
- )
15
+ from reconcile.utils.ocm import OCMMap
18
16
 
19
17
  QONTRACT_INTEGRATION = "ocm-upgrade-scheduler-org-updater"
20
18
 
@@ -238,7 +238,7 @@ def create_cluster_bots(
238
238
  def update_vault(
239
239
  cluster: ClusterV1, config: Config, token: str, admin_token: str | None
240
240
  ) -> None:
241
- vault = cast(_VaultClient, VaultClient())
241
+ vault = cast("_VaultClient", VaultClient())
242
242
  vault.write(
243
243
  {
244
244
  "path": vault_secret(cluster, config, cluster_admin=False)["path"],
@@ -63,7 +63,7 @@ def run(
63
63
  results.append(item)
64
64
 
65
65
  if not dry_run:
66
- vault_client = cast(_VaultClient, VaultClient())
66
+ vault_client = cast("_VaultClient", VaultClient())
67
67
  for item in results:
68
68
  secret = {
69
69
  "path": f"{vault_output_path}/{QONTRACT_INTEGRATION}/{item['cluster']}/{namespace_name}/{item['name']}",
@@ -1,6 +1,6 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Callable
3
+ from typing import TYPE_CHECKING
4
4
 
5
5
  from sretoolbox.utils import threaded
6
6
 
@@ -16,15 +16,19 @@ from reconcile.saas_auto_promotions_manager.merge_request_manager.renderer impor
16
16
  Renderer,
17
17
  )
18
18
  from reconcile.saas_auto_promotions_manager.meta import QONTRACT_INTEGRATION
19
- from reconcile.saas_auto_promotions_manager.publisher import Publisher
20
19
  from reconcile.saas_auto_promotions_manager.s3_exporter import S3Exporter
21
- from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
22
20
  from reconcile.utils.defer import defer
23
21
  from reconcile.utils.runtime.integration import (
24
22
  PydanticRunParams,
25
23
  QontractReconcileIntegration,
26
24
  )
27
25
 
26
+ if TYPE_CHECKING:
27
+ from collections.abc import Callable
28
+
29
+ from reconcile.saas_auto_promotions_manager.publisher import Publisher
30
+ from reconcile.saas_auto_promotions_manager.subscriber import Subscriber
31
+
28
32
 
29
33
  class SaasAutoPromotionsManagerParams(PydanticRunParams):
30
34
  thread_pool_size: int
@@ -1,11 +1,14 @@
1
1
  from __future__ import annotations
2
2
 
3
- from collections.abc import Iterable
4
3
  from dataclasses import dataclass
5
4
  from enum import Enum
5
+ from typing import TYPE_CHECKING
6
6
 
7
- from reconcile.saas_auto_promotions_manager.publisher import Publisher
8
- from reconcile.utils.state import State
7
+ if TYPE_CHECKING:
8
+ from collections.abc import Iterable
9
+
10
+ from reconcile.saas_auto_promotions_manager.publisher import Publisher
11
+ from reconcile.utils.state import State
9
12
 
10
13
 
11
14
  class DeploymentState(Enum):
@@ -14,7 +14,6 @@ from reconcile.typed_queries.saas_files import (
14
14
  get_saasherder_settings,
15
15
  )
16
16
  from reconcile.utils.defer import defer
17
- from reconcile.utils.jjb_client import JJB
18
17
  from reconcile.utils.saasherder import SaasHerder
19
18
  from reconcile.utils.secret_reader import create_secret_reader
20
19
  from reconcile.utils.semver_helper import make_semver
@@ -61,7 +60,7 @@ def run(dry_run: bool, defer: Callable | None = None) -> None:
61
60
  ]
62
61
  for p in missing_image_patterns:
63
62
  logging.error(f"image pattern is missing from quayOrgs: {p}")
64
- jjb: JJB = init_jjb(secret_reader)
63
+ jjb = init_jjb(secret_reader)
65
64
  saasherder.validate_upstream_jobs(jjb)
66
65
  if not saasherder.valid or missing_repos or missing_image_patterns:
67
66
  sys.exit(ExitCodes.ERROR)
@@ -2,8 +2,7 @@ from __future__ import annotations
2
2
 
3
3
  import hashlib
4
4
  import logging
5
- from collections.abc import Iterable
6
- from typing import Any
5
+ from typing import TYPE_CHECKING, Any
7
6
 
8
7
  from pydantic import BaseModel
9
8
 
@@ -14,6 +13,9 @@ from reconcile.gql_definitions.skupper_network.skupper_networks import (
14
13
  NamespaceV1,
15
14
  )
16
15
 
16
+ if TYPE_CHECKING:
17
+ from collections.abc import Iterable
18
+
17
19
 
18
20
  class SkupperCluster(BaseModel):
19
21
  name: str
@@ -170,7 +170,7 @@ class AtlassianStatusPageProvider:
170
170
  self._group_id_to_name: dict[str, str] = {}
171
171
  self._build_component_cache()
172
172
 
173
- def _build_component_cache(self):
173
+ def _build_component_cache(self) -> None:
174
174
  self._components = self._api.list_components()
175
175
  self._components_by_id = {c.id: c for c in self._components}
176
176
  self._components_by_displayname = {c.name: c for c in self._components}
@@ -164,7 +164,7 @@ class StatusMaintenance(BaseModel):
164
164
 
165
165
  statuspage_announcements = [
166
166
  StatusMaintenanceAnnouncement.init_from_announcement(
167
- cast(MaintenanceStatuspageAnnouncementV1, m)
167
+ cast("MaintenanceStatuspageAnnouncementV1", m)
168
168
  )
169
169
  for m in maintenance.announcements or []
170
170
  if m.provider == PROVIDER_NAME
@@ -272,7 +272,7 @@ def _write_external_resource_secrets_to_vault(
272
272
  separate module if we have additional needs for a similar function.
273
273
  """
274
274
  integration_name = integration_name.replace("_", "-")
275
- vault_client = cast(_VaultClient, VaultClient())
275
+ vault_client = cast("_VaultClient", VaultClient())
276
276
  for spec in resource_specs.values():
277
277
  # A secret can be empty if the terraform-* integrations are not enabled on the cluster
278
278
  # the resource is defined on - lets skip vault writes for those right now and
@@ -314,7 +314,7 @@ def write_outputs_to_vault(
314
314
  vault_path: str, resource_specs: ExternalResourceSpecInventory
315
315
  ) -> None:
316
316
  integration_name = QONTRACT_INTEGRATION.replace("_", "-")
317
- vault_client = cast(_VaultClient, VaultClient())
317
+ vault_client = cast("_VaultClient", VaultClient())
318
318
  for spec in resource_specs.values():
319
319
  # a secret can be empty if the terraform-integration is not enabled on the cluster
320
320
  # the resource is defined on - lets skip vault writes for those right now and
@@ -155,7 +155,7 @@ def _build_desired_state_items(
155
155
  for peer_connection in cluster_info.peering.connections: # type: ignore[union-attr]
156
156
  if _is_tgw_peer_connection(peer_connection, account_name):
157
157
  yield from _build_desired_state_tgw_connection(
158
- cast(ClusterPeeringConnectionAccountTGWV1, peer_connection),
158
+ cast("ClusterPeeringConnectionAccountTGWV1", peer_connection),
159
159
  cluster_info,
160
160
  ocm,
161
161
  awsapi,
@@ -367,7 +367,7 @@ def _is_tgw_peer_connection(
367
367
  return False
368
368
  if account_name is None:
369
369
  return True
370
- tgw_peer_connection = cast(ClusterPeeringConnectionAccountTGWV1, peer_connection)
370
+ tgw_peer_connection = cast("ClusterPeeringConnectionAccountTGWV1", peer_connection)
371
371
  return tgw_peer_connection.account.name == account_name
372
372
 
373
373
 
@@ -397,7 +397,7 @@ def _filter_tgw_accounts(
397
397
  for peer_connection in cluster.peering.connections: # type: ignore[union-attr]
398
398
  if peer_connection.provider == TGW_CONNECTION_PROVIDER:
399
399
  tgw_peer_connection = cast(
400
- ClusterPeeringConnectionAccountTGWV1, peer_connection
400
+ "ClusterPeeringConnectionAccountTGWV1", peer_connection
401
401
  )
402
402
  tgw_account_names.add(tgw_peer_connection.account.name)
403
403
  return [
@@ -295,7 +295,7 @@ def run(
295
295
  new_users = tf.get_new_users()
296
296
 
297
297
  if reencrypt_settings:
298
- vc = cast(_VaultClient, VaultClient())
298
+ vc = cast("_VaultClient", VaultClient())
299
299
  write_user_to_vault(
300
300
  vc, reencrypt_settings.reencrypt_vault_path, new_users, skip_accounts
301
301
  )
@@ -1,13 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  import operator
3
5
  import os
4
6
  import re
5
- from collections.abc import (
6
- Iterable,
7
- Iterator,
8
- Mapping,
9
- Sequence,
10
- )
11
7
  from functools import lru_cache
12
8
  from threading import Lock
13
9
  from typing import (
@@ -20,7 +16,6 @@ from typing import (
20
16
  )
21
17
 
22
18
  from boto3 import Session
23
- from botocore.client import BaseClient
24
19
  from botocore.config import Config
25
20
  from pydantic import BaseModel
26
21
  from sretoolbox.utils import threaded
@@ -30,6 +25,14 @@ import reconcile.utils.lean_terraform_client as terraform
30
25
  from reconcile.utils.secret_reader import SecretReader, SecretReaderBase
31
26
 
32
27
  if TYPE_CHECKING:
28
+ from collections.abc import (
29
+ Iterable,
30
+ Iterator,
31
+ Mapping,
32
+ Sequence,
33
+ )
34
+
35
+ from botocore.client import BaseClient
33
36
  from mypy_boto3_dynamodb import DynamoDBClient, DynamoDBServiceResource
34
37
  from mypy_boto3_ec2 import (
35
38
  EC2Client,
@@ -77,27 +80,6 @@ if TYPE_CHECKING:
77
80
  from mypy_boto3_support import SupportClient
78
81
  from mypy_boto3_support.type_defs import CaseDetailsTypeDef
79
82
 
80
- else:
81
- AccessKeyMetadataTypeDef = CaseDetailsTypeDef = CloudWatchLogsClient = (
82
- DBInstanceMessageTypeDef
83
- ) = DBRecommendationsMessageTypeDef = DynamoDBClient = DynamoDBServiceResource = (
84
- EC2Client
85
- ) = EC2ServiceResource = ECRClient = ElasticLoadBalancingClient = FilterTypeDef = (
86
- HostedZoneTypeDef
87
- ) = IAMClient = IAMServiceResource = ImageTypeDef = (
88
- LaunchPermissionModificationsTypeDef
89
- ) = LogGroupTypeDef = OrganizationsClient = RDSClient = ResourceRecordSetTypeDef = (
90
- ResourceRecordTypeDef
91
- ) = Route53Client = RouteTableTypeDef = S3Client = S3ServiceResource = SQSClient = (
92
- SQSServiceResource
93
- ) = STSClient = SubnetTypeDef = SupportClient = TagTypeDef = (
94
- TransitGatewayTypeDef
95
- ) = TransitGatewayVpcAttachmentTypeDef = UpgradeTargetTypeDef = (
96
- VpcEndpointTypeDef
97
- ) = VpcTypeDef = NetworkInterfaceTypeDef = LoadBalancerDescriptionTypeDef = (
98
- TagDescriptionTypeDef
99
- ) = object
100
-
101
83
 
102
84
  class InvalidResourceTypeError(Exception):
103
85
  pass
@@ -461,7 +443,7 @@ class AWSApi:
461
443
  self, account_name: str, region_name: str | None = None
462
444
  ) -> S3Client:
463
445
  session = self.get_session(account_name)
464
- return cast(S3Client, self.get_session_client(session, "s3", region_name))
446
+ return cast("S3Client", self.get_session_client(session, "s3", region_name))
465
447
 
466
448
  def init_users(self) -> None:
467
449
  self.users = {}
@@ -1452,7 +1434,7 @@ class AWSApi:
1452
1434
  @staticmethod
1453
1435
  def _get_vpc_endpoints(
1454
1436
  filters: Sequence[FilterTypeDef], ec2: EC2Client
1455
- ) -> list["VpcEndpointTypeDef"]:
1437
+ ) -> list[VpcEndpointTypeDef]:
1456
1438
  atts = ec2.describe_vpc_endpoints(Filters=filters)
1457
1439
  return atts.get("VpcEndpoints", [])
1458
1440
 
@@ -1,14 +1,14 @@
1
+ from __future__ import annotations
2
+
1
3
  import logging
2
4
  from enum import StrEnum
3
5
  from typing import TYPE_CHECKING
4
6
 
7
+ from pydantic import BaseModel
8
+
5
9
  if TYPE_CHECKING:
6
10
  from mypy_boto3_account import AccountClient
7
11
  from mypy_boto3_account.type_defs import AlternateContactTypeDef
8
- else:
9
- AccountClient = AlternateContactTypeDef = object
10
-
11
- from pydantic import BaseModel
12
12
 
13
13
 
14
14
  class OptStatus(StrEnum):
@@ -3,10 +3,9 @@ from __future__ import annotations
3
3
  import textwrap
4
4
  from abc import ABC, abstractmethod
5
5
  from functools import cached_property
6
- from typing import Any, TypeVar
6
+ from typing import TYPE_CHECKING, Any, TypeVar
7
7
 
8
8
  from boto3 import Session
9
- from botocore.client import BaseClient
10
9
  from pydantic import BaseModel
11
10
 
12
11
  import reconcile.utils.aws_api_typed.account
@@ -26,6 +25,9 @@ from reconcile.utils.aws_api_typed.service_quotas import AWSApiServiceQuotas
26
25
  from reconcile.utils.aws_api_typed.sts import AWSApiSts
27
26
  from reconcile.utils.aws_api_typed.support import AWSApiSupport
28
27
 
28
+ if TYPE_CHECKING:
29
+ from botocore.client import BaseClient
30
+
29
31
  SubApi = TypeVar(
30
32
  "SubApi",
31
33
  AWSApiAccount,
@@ -1,9 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import TYPE_CHECKING
2
4
 
3
5
  if TYPE_CHECKING:
4
6
  from mypy_boto3_dynamodb import DynamoDBClient
5
- else:
6
- DynamoDBClient = object
7
7
 
8
8
 
9
9
  class AWSApiDynamoDB:
@@ -1,3 +1,5 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import TYPE_CHECKING
2
4
 
3
5
  import botocore
@@ -5,8 +7,6 @@ from pydantic import BaseModel, Field
5
7
 
6
8
  if TYPE_CHECKING:
7
9
  from mypy_boto3_iam import IAMClient
8
- else:
9
- IAMClient = object
10
10
 
11
11
 
12
12
  class AWSAccessKey(BaseModel):
@@ -1,26 +1,29 @@
1
+ from __future__ import annotations
2
+
1
3
  import functools
2
- from collections.abc import Iterable, Mapping
3
- from typing import TYPE_CHECKING, Optional
4
+ from typing import TYPE_CHECKING
4
5
 
5
6
  from pydantic import BaseModel, Field
6
7
 
7
8
  if TYPE_CHECKING:
9
+ from collections.abc import Iterable, Mapping
10
+
8
11
  from mypy_boto3_organizations import OrganizationsClient
9
12
  from mypy_boto3_organizations.literals import CreateAccountFailureReasonType
10
13
  else:
11
- OrganizationsClient = object
12
- CreateAccountFailureReasonType = object
14
+ # pydantic needs these types to be defined during runtime
15
+ CreateAccountFailureReasonType = str
13
16
 
14
17
 
15
18
  class AwsOrganizationOU(BaseModel):
16
19
  id: str = Field(..., alias="Id")
17
20
  arn: str = Field(..., alias="Arn")
18
21
  name: str = Field(..., alias="Name")
19
- children: list["AwsOrganizationOU"] = []
22
+ children: list[AwsOrganizationOU] = []
20
23
 
21
24
  def locate(
22
25
  self, path: list[str], ignore_case: bool = True
23
- ) -> Optional["AwsOrganizationOU"]:
26
+ ) -> AwsOrganizationOU | None:
24
27
  name, *sub = path
25
28
  match = self.name.lower() == name.lower() if ignore_case else self.name == name
26
29
  if not match:
@@ -36,7 +39,7 @@ class AwsOrganizationOU(BaseModel):
36
39
  None,
37
40
  )
38
41
 
39
- def find(self, path: str, ignore_case: bool = True) -> "AwsOrganizationOU":
42
+ def find(self, path: str, ignore_case: bool = True) -> AwsOrganizationOU:
40
43
  node = self.locate(path.strip("/").split("/"), ignore_case=ignore_case)
41
44
  if not node:
42
45
  raise KeyError(f"OU not found: {path}")
@@ -1,10 +1,9 @@
1
+ from __future__ import annotations
2
+
1
3
  from typing import TYPE_CHECKING
2
4
 
3
5
  if TYPE_CHECKING:
4
6
  from mypy_boto3_s3 import S3Client
5
- from mypy_boto3_s3.literals import BucketLocationConstraintType
6
- else:
7
- S3Client = BucketLocationConstraintType = object
8
7
 
9
8
 
10
9
  class AWSApiS3: