ronantakizawa/codereview-bench huggingface dataset:
Repository: ansible/awx
File: awx/main/models/inventory.py (Python)

Code before:
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

import copy

# Python
import datetime
import logging
import os.path
import re
import time
from urllib.parse import urljoin

from ansible_base.lib.utils.models import prevent_search
from awx_plugins.inventory.plugins import PluginFileInjector

# Django
from django.conf import settings
from django.core.exceptions import ValidationError
from django.db import connection, models, transaction
from django.db.models import Q
from django.urls import resolve
from django.utils.timezone import now
from django.utils.translation import gettext_lazy as _

# REST Framework
from rest_framework.exceptions import ParseError

# AWX
from awx.api.versioning import reverse
from awx.main.constants import CLOUD_PROVIDERS
from awx.main.consumers import emit_channel_notification
from awx.main.fields import ImplicitRoleField, OrderedManyToManyField, SmartFilterField
from awx.main.managers import HostManager, HostMetricActiveManager
from awx.main.models.base import CLOUD_INVENTORY_SOURCES, BaseModel, CommonModelNameNotUnique, VarsDictProperty, accepts_json
from awx.main.models.events import InventoryUpdateEvent, UnpartitionedInventoryUpdateEvent
from awx.main.models.mixins import CustomVirtualEnvMixin, RelatedJobsMixin, ResourceMixin, TaskManagerInventoryUpdateMixin
from awx.main.models.notifications import JobNotificationMixin, NotificationTemplate
from awx.main.models.unified_jobs import UnifiedJob, UnifiedJobTemplate

Review comment (bug):
Let's keep the order of the imports as it was. Making formatting changes in functional PRs extends their scope to unlimited, meaning that those things that's gone wrong with formatting will now block the entire PR even if the original functional change is complete.
Besides, it's customary to have generic frameworks before libraries.

Code after:
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

# Python
import datetime
import time
import logging
import re
import copy
import os.path
from urllib.parse import urljoin

# Django
from django.conf import settings
from django.db import models, connection
from django.utils.translation import gettext_lazy as _
from django.db import transaction
from django.core.exceptions import ValidationError
from django.urls import resolve
from django.utils.timezone import now
from django.db.models import Q

# REST Framework
from rest_framework.exceptions import ParseError

from ansible_base.lib.utils.models import prevent_search
from awx_plugins.inventory.plugins import PluginFileInjector

# AWX
from awx.api.versioning import reverse
from awx.main.utils.plugins import discover_available_cloud_provider_plugin_names, compute_cloud_inventory_sources
from awx.main.consumers import emit_channel_notification
from awx.main.fields import (
    ImplicitRoleField,
    SmartFilterField,
    OrderedManyToManyField,
)
from awx.main.managers import HostManager, HostMetricActiveManager
from awx.main.models.base import BaseModel, CommonModelNameNotUnique, VarsDictProperty, accepts_json
Repository: ansible/awx
File: awx/main/utils/plugins.py (Python)

Code before:
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

"""
This module is designed to house dynamically generated plugins.
"""
__all__ = ['CLOUD_PROVIDERS']
CLOUD_PROVIDERS = []


def discover_available_cloud_provider_plugin_names():
    global CLOUD_PROVIDERS
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    CLOUD_PROVIDERS = plugin_names


Review comment (suggestion):
FYI, the copyright year is for when content got created. Since you just wrote this code, it's probably
```suggestion
# Copyright (c) 2024 Ansible, Inc.
```
in this case.

Code after:
# Copyright (c) 2024 Ansible, Inc.
# All Rights Reserved.

"""
This module contains the code responsible for extracting the lists of dynamically discovered plugins.
"""

from functools import cache


@cache
def discover_available_cloud_provider_plugin_names() -> list[str]:
    """
    Return a list of cloud plugin names available in runtime.

    The discovery result is cached since it does not change throughout
    the life cycle of the server run.

    :returns: List of plugin cloud names.
    :rtype: list[str]
    """
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    plugin_names.remove('constructed')
Repository: ansible/awx
File: awx/main/models/base.py (Python)

Code before:
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

# Django
from django.db import models
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now

# django-ansible-base
from ansible_base.lib.utils.models import get_type_for_model

# Django-CRUM
from crum import get_current_user

# AWX
from awx.main.utils import encrypt_field, parse_yaml_or_json
from awx.main.utils.plugins import CLOUD_PROVIDERS

__all__ = [
    'VarsDictProperty',
    'BaseModel',
    'CreatedModifiedModel',
    'PasswordFieldsModel',
    'PrimordialModel',
    'CommonModel',
    'CommonModelNameNotUnique',
    'NotificationFieldsModel',
    'PERM_INVENTORY_DEPLOY',
    'PERM_INVENTORY_SCAN',
    'PERM_INVENTORY_CHECK',
    'JOB_TYPE_CHOICES',
    'AD_HOC_JOB_TYPE_CHOICES',
    'PROJECT_UPDATE_JOB_TYPE_CHOICES',
    'CLOUD_INVENTORY_SOURCES',
    'VERBOSITY_CHOICES',
]

PERM_INVENTORY_DEPLOY = 'run'
PERM_INVENTORY_CHECK = 'check'
PERM_INVENTORY_SCAN = 'scan'

JOB_TYPE_CHOICES = [

Review comment (refactor):
```suggestion
from awx.main.utils.plugins import discover_available_cloud_provider_plugin_names
```
and call it below.
Though, it seems that it's being used during import time which has the same problem with the execution order and that `CLOUD_INVENTORY_SOURCES` construction and use need to be refactored similarly.

Code after:
# Copyright (c) 2015 Ansible, Inc.
# All Rights Reserved.

# Django
from django.db import models
from django.core.exceptions import ValidationError, ObjectDoesNotExist
from django.utils.translation import gettext_lazy as _
from django.utils.timezone import now

# django-ansible-base
from ansible_base.lib.utils.models import get_type_for_model

# Django-CRUM
from crum import get_current_user

# AWX
from awx.main.utils import encrypt_field, parse_yaml_or_json

__all__ = [
    'VarsDictProperty',
    'BaseModel',
    'CreatedModifiedModel',
    'PasswordFieldsModel',
    'PrimordialModel',
    'CommonModel',
    'CommonModelNameNotUnique',
    'NotificationFieldsModel',
    'PERM_INVENTORY_DEPLOY',
    'PERM_INVENTORY_SCAN',
    'PERM_INVENTORY_CHECK',
    'JOB_TYPE_CHOICES',
    'AD_HOC_JOB_TYPE_CHOICES',
    'PROJECT_UPDATE_JOB_TYPE_CHOICES',
    'VERBOSITY_CHOICES',
]

PERM_INVENTORY_DEPLOY = 'run'
PERM_INVENTORY_CHECK = 'check'
PERM_INVENTORY_SCAN = 'scan'

JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
Repository: ansible/awx
File: awx/main/tests/functional/models/test_inventory.py (Python)

Code before:
# -*- coding: utf-8 -*-

import pytest
from unittest import mock

# AWX
from awx.main.models import Host, Inventory, InventorySource, InventoryUpdate, CredentialType, Credential, Job
from awx.main.utils.filters import SmartFilter
from awx.main.utils.plugins import CLOUD_PROVIDERS


@pytest.mark.django_db
class TestInventoryScript:
    def test_hostvars(self, inventory):
        inventory.hosts.create(name='ahost', variables={"foo": "bar"})
        assert inventory.get_script_data(hostvars=True)['_meta']['hostvars']['ahost'] == {'foo': 'bar'}

    def test_towervars(self, inventory):
        host = inventory.hosts.create(name='ahost')
        assert inventory.get_script_data(hostvars=True, towervars=True)['_meta']['hostvars']['ahost'] == {
            'remote_tower_enabled': 'true',
            'remote_tower_id': host.id,
            'remote_host_enabled': 'true',
            'remote_host_id': host.id,
        }

    def test_all_group(self, inventory):
        inventory.groups.create(name='all', variables={'a1': 'a1'})
        # make sure we return a1 details in output
        data = inventory.get_script_data()
        assert 'all' in data
        assert data['all'] == {'vars': {'a1': 'a1'}}

    def test_empty_group(self, inventory):

Review comment (suggestion):
This one seems easy and doesn't require that subtest dance..
```suggestion
from awx.main.utils.plugins import discover_available_cloud_provider_plugin_names
```

Code after:
# -*- coding: utf-8 -*-

import pytest
from unittest import mock

# AWX
from awx.main.models import Host, Inventory, InventorySource, InventoryUpdate, CredentialType, Credential, Job
from awx.main.utils.filters import SmartFilter
from awx.main.utils.plugins import discover_available_cloud_provider_plugin_names


@pytest.mark.django_db
class TestInventoryScript:
    def test_hostvars(self, inventory):
        inventory.hosts.create(name='ahost', variables={"foo": "bar"})
        assert inventory.get_script_data(hostvars=True)['_meta']['hostvars']['ahost'] == {'foo': 'bar'}

    def test_towervars(self, inventory):
        host = inventory.hosts.create(name='ahost')
        assert inventory.get_script_data(hostvars=True, towervars=True)['_meta']['hostvars']['ahost'] == {
            'remote_tower_enabled': 'true',
            'remote_tower_id': host.id,
            'remote_host_enabled': 'true',
            'remote_host_id': host.id,
        }

    def test_all_group(self, inventory):
        inventory.groups.create(name='all', variables={'a1': 'a1'})
        # make sure we return a1 details in output
        data = inventory.get_script_data()
        assert 'all' in data
        assert data['all'] == {'vars': {'a1': 'a1'}}

    def test_empty_group(self, inventory):
Repository: ansible/awx
File: awx/main/utils/plugins.py (Python)

Code before:
# Copyright (c) 2024 Ansible, Inc.
# All Rights Reserved.

"""
This module contains the code responsible for extracting the lists of dynamically generated plugins.
"""

CLOUD_PROVIDERS = []


def discover_available_cloud_provider_plugin_names():
    global CLOUD_PROVIDERS
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    CLOUD_PROVIDERS = plugin_names


Review comment (performance):
Since this is at the end of the diff, I'm coping the suggested change from https://github.com/ansible/awx/pull/15537/files#r1782889259:
```suggestion
from functools import cache


@cache
def discover_available_cloud_provider_plugin_names() -> list[str]:
    """Return a list of cloud plugin names available in runtime.

    The discovery result is cached since it does not change throughout
    the life cycle of the server run.
    
    :returns: List of plugin cloud names.
    :rtype: list[str]
    """
    from awx.main.models.inventory import InventorySourceOptions

    return list(InventorySourceOptions.injectors.keys())
```

Code after:
# Copyright (c) 2024 Ansible, Inc.
# All Rights Reserved.

"""
This module contains the code responsible for extracting the lists of dynamically discovered plugins.
"""

from functools import cache


@cache
def discover_available_cloud_provider_plugin_names() -> list[str]:
    """
    Return a list of cloud plugin names available in runtime.

    The discovery result is cached since it does not change throughout
    the life cycle of the server run.

    :returns: List of plugin cloud names.
    :rtype: list[str]
    """
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    plugin_names.remove('constructed')

    return plugin_names


@cache
def compute_cloud_inventory_sources() -> dict[str, str]:
    """
    Return a dictionary of cloud provider plugin names
    available plus source control management and constructed.

    :returns: Dictionary of plugin cloud names plus source control.
    :rtype: dict[str, str]
    """

    plugins = discover_available_cloud_provider_plugin_names()
Repository: ansible/awx
File: awx/main/utils/plugins.py (Python)

Code before:
# Copyright (c) 2024 Ansible, Inc.
# All Rights Reserved.

"""
This module contains the code responsible for extracting the lists of dynamically generated plugins.
"""

CLOUD_PROVIDERS = []


def discover_available_cloud_provider_plugin_names():
    global CLOUD_PROVIDERS
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    CLOUD_PROVIDERS = plugin_names


Review comment (refactor):
```suggestion
This module contains the code responsible for extracting the lists of dynamically discovered plugins.
```

Code after:
# Copyright (c) 2024 Ansible, Inc.
# All Rights Reserved.

"""
This module contains the code responsible for extracting the lists of dynamically discovered plugins.
"""

from functools import cache


@cache
def discover_available_cloud_provider_plugin_names() -> list[str]:
    """
    Return a list of cloud plugin names available in runtime.

    The discovery result is cached since it does not change throughout
    the life cycle of the server run.

    :returns: List of plugin cloud names.
    :rtype: list[str]
    """
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    plugin_names.remove('constructed')

    return plugin_names
Repository: ansible/awx
File: awx/main/models/base.py (Python)

Code before:
PERM_INVENTORY_SCAN = 'scan'

JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
    (PERM_INVENTORY_SCAN, _('Scan')),
]

NEW_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

AD_HOC_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

PROJECT_UPDATE_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]


def discover_cloud_inventory_sources():
    return list(discover_available_cloud_provider_plugin_names()) + ['scm']


VERBOSITY_CHOICES = [
    (0, '0 (Normal)'),
    (1, '1 (Verbose)'),
    (2, '2 (More Verbose)'),
    (3, '3 (Debug)'),
    (4, '4 (Connection Debug)'),
    (5, '5 (WinRM Debug)'),
]


class VarsDictProperty(object):
    """
    Retrieve a string of variables in YAML or JSON as a dictionary.
    """

    def __init__(self, field='variables', key_value=False):
        self.field = field
        self.key_value = key_value

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        v = getattr(obj, self.field)

Review comment (suggestion):
It already returns a list, according to the type annotations, so it's enough to do
```suggestion
    return discover_available_cloud_provider_plugin_names() + ['scm']
```
or
```suggestion
    return [*discover_available_cloud_provider_plugin_names(), 'scm']
```

Code after:

JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
    (PERM_INVENTORY_SCAN, _('Scan')),
]

NEW_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

AD_HOC_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

PROJECT_UPDATE_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]


VERBOSITY_CHOICES = [
    (0, '0 (Normal)'),
    (1, '1 (Verbose)'),
    (2, '2 (More Verbose)'),
    (3, '3 (Debug)'),
    (4, '4 (Connection Debug)'),
    (5, '5 (WinRM Debug)'),
]


class VarsDictProperty(object):
    """
    Retrieve a string of variables in YAML or JSON as a dictionary.
    """

    def __init__(self, field='variables', key_value=False):
        self.field = field
        self.key_value = key_value

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        v = getattr(obj, self.field)
        if hasattr(v, 'items'):
            return v
        v = v.encode('utf-8')
        return parse_yaml_or_json(v)
Repository: ansible/awx
File: awx/main/models/base.py (Python)

Code before:
PERM_INVENTORY_CHECK = 'check'
PERM_INVENTORY_SCAN = 'scan'

JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
    (PERM_INVENTORY_SCAN, _('Scan')),
]

NEW_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

AD_HOC_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

PROJECT_UPDATE_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]


def compute_cloud_inventory_sources():
    """Return a list of cloud provider plugin names
    available plus source control management.

    :returns: List of plugin cloud names plus sou.
    :rtype: list[str]
    """
    return discover_available_cloud_provider_plugin_names() + ['scm']


VERBOSITY_CHOICES = [
    (0, '0 (Normal)'),
    (1, '1 (Verbose)'),
    (2, '2 (More Verbose)'),
    (3, '3 (Debug)'),
    (4, '4 (Connection Debug)'),
    (5, '5 (WinRM Debug)'),
]


class VarsDictProperty(object):
    """
    Retrieve a string of variables in YAML or JSON as a dictionary.
    """

    def __init__(self, field='variables', key_value=False):

Review comment (suggestion):
```suggestion
def compute_cloud_inventory_sources() -> list[str]:
```

Code after:
PERM_INVENTORY_SCAN = 'scan'

JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
    (PERM_INVENTORY_SCAN, _('Scan')),
]

NEW_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

AD_HOC_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

PROJECT_UPDATE_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]


VERBOSITY_CHOICES = [
    (0, '0 (Normal)'),
    (1, '1 (Verbose)'),
    (2, '2 (More Verbose)'),
    (3, '3 (Debug)'),
    (4, '4 (Connection Debug)'),
    (5, '5 (WinRM Debug)'),
]


class VarsDictProperty(object):
    """
    Retrieve a string of variables in YAML or JSON as a dictionary.
    """

    def __init__(self, field='variables', key_value=False):
        self.field = field
        self.key_value = key_value

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        v = getattr(obj, self.field)
        if hasattr(v, 'items'):
            return v
        v = v.encode('utf-8')
        return parse_yaml_or_json(v)
Repository: ansible/awx
File: awx/main/models/base.py (Python)

Code before:

NEW_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

AD_HOC_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

PROJECT_UPDATE_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]


def compute_cloud_inventory_sources() -> list[str]:
    """Return a list of cloud provider plugin names
    available plus source control management.

    :returns: List of plugin cloud names plus sou.
    :rtype: list[str]
    """
    return discover_available_cloud_provider_plugin_names() + ['scm']


VERBOSITY_CHOICES = [
    (0, '0 (Normal)'),
    (1, '1 (Verbose)'),
    (2, '2 (More Verbose)'),
    (3, '3 (Debug)'),
    (4, '4 (Connection Debug)'),
    (5, '5 (WinRM Debug)'),
]


class VarsDictProperty(object):
    """
    Retrieve a string of variables in YAML or JSON as a dictionary.
    """

    def __init__(self, field='variables', key_value=False):
        self.field = field
        self.key_value = key_value

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        v = getattr(obj, self.field)
        if hasattr(v, 'items'):

Review comment (suggestion):
Perhaps, this should also move to `awx/main/utils/plugins.py` since it's not a model?
```suggestion
```

Code after:
NEW_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

AD_HOC_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]

PROJECT_UPDATE_JOB_TYPE_CHOICES = [
    (PERM_INVENTORY_DEPLOY, _('Run')),
    (PERM_INVENTORY_CHECK, _('Check')),
]


VERBOSITY_CHOICES = [
    (0, '0 (Normal)'),
    (1, '1 (Verbose)'),
    (2, '2 (More Verbose)'),
    (3, '3 (Debug)'),
    (4, '4 (Connection Debug)'),
    (5, '5 (WinRM Debug)'),
]


class VarsDictProperty(object):
    """
    Retrieve a string of variables in YAML or JSON as a dictionary.
    """

    def __init__(self, field='variables', key_value=False):
        self.field = field
        self.key_value = key_value

    def __get__(self, obj, type=None):
        if obj is None:
            return self
        v = getattr(obj, self.field)
        if hasattr(v, 'items'):
            return v
        v = v.encode('utf-8')
        return parse_yaml_or_json(v)

    def __set__(self, obj, value):
        raise AttributeError('readonly property')


class BaseModel(models.Model):
    """
    Base model class with common methods for all models.
Repository: ansible/awx
File: awx/main/utils/plugins.py (Python)

Code before:
"""
This module contains the code responsible for extracting the lists of dynamically discovered plugins.
"""

from functools import cache


@cache
def discover_available_cloud_provider_plugin_names() -> list[str]:
    """Return a list of cloud plugin names available in runtime.

    The discovery result is cached since it does not change throughout
    the life cycle of the server run.

    :returns: List of plugin cloud names.
    :rtype: list[str]
    """
    from awx.main.models.inventory import InventorySourceOptions

    return list(InventorySourceOptions.injectors.keys())


def compute_cloud_inventory_sources() -> list[str]:
    """Return a list of cloud provider plugin names
    available plus source control management.
    :returns: List of plugin cloud names plus sou.
    :rtype: list[str]
    """
    return discover_available_cloud_provider_plugin_names() + ['scm']


Review comment (suggestion):
PEP 257 says the docstring title should be separated from the body by an empty line:
```suggestion

    :returns: List of plugin cloud names plus source control.
```

Code after:
"""
This module contains the code responsible for extracting the lists of dynamically discovered plugins.
"""

from functools import cache


@cache
def discover_available_cloud_provider_plugin_names() -> list[str]:
    """
    Return a list of cloud plugin names available in runtime.

    The discovery result is cached since it does not change throughout
    the life cycle of the server run.

    :returns: List of plugin cloud names.
    :rtype: list[str]
    """
    from awx.main.models.inventory import InventorySourceOptions

    plugin_names = list(InventorySourceOptions.injectors.keys())

    plugin_names.remove('constructed')

    return plugin_names


@cache
def compute_cloud_inventory_sources() -> dict[str, str]:
    """
    Return a dictionary of cloud provider plugin names
    available plus source control management and constructed.

    :returns: Dictionary of plugin cloud names plus source control.
    :rtype: dict[str, str]
    """

    plugins = discover_available_cloud_provider_plugin_names()

    return dict(zip(plugins, plugins), scm='scm', constructed='constructed')


@cache
def load_combined_inventory_source_options() -> dict[str, str]:
    """
    Return a dictionary of cloud provider plugin names and 'file'.

    The 'file' entry is included separately since it needs to be consumed directly by the serializer.

    :returns: A dictionary of cloud provider plugin names (as both keys and values) plus the 'file' entry.
    :rtype: dict[str, str]