Use sentinel everywhere (#84041)

* Use sentinel everywhere

Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
pull/84043/head
Abhijeet Kasurde 2 months ago committed by GitHub
parent 9abc651cd6
commit b3c4154e86
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194

@ -17,6 +17,7 @@ from collections.abc import Mapping, Sequence
from jinja2.nativetypes import NativeEnvironment
from ansible.errors import AnsibleOptionsError, AnsibleError, AnsibleRequiredOptionError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_text, to_bytes, to_native
from ansible.module_utils.common.yaml import yaml_load
from ansible.module_utils.six import string_types
@ -232,15 +233,13 @@ def find_ini_config_file(warnings=None):
# Note: In this case, warnings does nothing
warnings = set()
# A value that can never be a valid path so that we can tell if ANSIBLE_CONFIG was set later
# We can't use None because we could set path to None.
SENTINEL = object
potential_paths = []
# A value that can never be a valid path so that we can tell if ANSIBLE_CONFIG was set later
# We can't use None because we could set path to None.
# Environment setting
path_from_env = os.getenv("ANSIBLE_CONFIG", SENTINEL)
if path_from_env is not SENTINEL:
path_from_env = os.getenv("ANSIBLE_CONFIG", Sentinel)
if path_from_env is not Sentinel:
path_from_env = unfrackpath(path_from_env, follow=False)
if os.path.isdir(to_bytes(path_from_env)):
path_from_env = os.path.join(path_from_env, "ansible.cfg")

@ -126,13 +126,13 @@ from ansible.galaxy.dependency_resolution.dataclasses import (
from ansible.galaxy.dependency_resolution.versioning import meets_requirements
from ansible.plugins.loader import get_all_plugin_loaders
from ansible.module_utils.common.file import S_IRWU_RG_RO, S_IRWXU_RXG_RXO, S_IXANY
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.common.collections import is_sequence
from ansible.module_utils.common.yaml import yaml_dump
from ansible.utils.collection_loader import AnsibleCollectionRef
from ansible.utils.display import Display
from ansible.utils.hashing import secure_hash, secure_hash_s
from ansible.utils.sentinel import Sentinel
display = Display()

@ -33,10 +33,10 @@ from ansible.module_utils.common.text.converters import to_bytes, to_native, to_
from ansible.module_utils.api import retry_with_delays_and_condition
from ansible.module_utils.api import generate_jittered_backoff
from ansible.module_utils.common.process import get_bin_path
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.yaml import yaml_load
from ansible.module_utils.urls import open_url
from ansible.utils.display import Display
from ansible.utils.sentinel import Sentinel
import yaml

@ -30,6 +30,7 @@ from urllib.error import HTTPError
from ansible import constants as C
from ansible.galaxy.api import GalaxyError
from ansible.galaxy.user_agent import user_agent
from ansible.module_utils.common.sentinel import Sentinel as NoTokenSentinel
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.common.yaml import yaml_dump, yaml_load
from ansible.module_utils.urls import open_url
@ -38,12 +39,6 @@ from ansible.utils.display import Display
display = Display()
class NoTokenSentinel(object):
""" Represents an ansible.cfg server with not token defined (will ignore cmdline and GALAXY_TOKEN_PATH. """
def __new__(cls, *args, **kwargs):
return cls
class KeycloakToken(object):
'''A token granted by a Keycloak server.

@ -0,0 +1,66 @@
# Copyright (c) 2019 Ansible Project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import annotations
class Sentinel:
"""
Object which can be used to mark whether an entry as being special
A sentinel value demarcates a value or marks an entry as having a special meaning. In C, the
Null byte is used as a sentinel for the end of a string. In Python, None is often used as
a Sentinel in optional parameters to mean that the parameter was not set by the user.
You should use None as a Sentinel value any Python code where None is not a valid entry. If
None is a valid entry, though, then you need to create a different value, which is the purpose
of this class.
Example of using Sentinel as a default parameter value::
def confirm_big_red_button(tristate=Sentinel):
if tristate is Sentinel:
print('You must explicitly press the big red button to blow up the base')
elif tristate is True:
print('Countdown to destruction activated')
elif tristate is False:
print('Countdown stopped')
elif tristate is None:
print('Waiting for more input')
Example of using Sentinel to tell whether a dict which has a default value has been changed::
values = {'one': Sentinel, 'two': Sentinel}
defaults = {'one': 1, 'two': 2}
# [.. Other code which does things including setting a new value for 'one' ..]
values['one'] = None
# [..]
print('You made changes to:')
for key, value in values.items():
if value is Sentinel:
continue
print('%s: %s' % (key, value)
"""
def __new__(cls):
"""
Return the cls itself. This makes both equality and identity True for comparing the class
to an instance of the class, preventing common usage errors.
Preferred usage::
a = Sentinel
if a is Sentinel:
print('Sentinel value')
However, these are True as well, eliminating common usage errors::
if Sentinel is Sentinel():
print('Sentinel value')
if Sentinel == Sentinel():
print('Sentinel value')
"""
return cls

@ -239,7 +239,7 @@ from grp import getgrnam, getgrgid
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.common.text.converters import to_bytes, to_native
from ansible.module_utils.common.sentinel import Sentinel
# There will only be a single AnsibleModule object per module
module = None
@ -257,11 +257,6 @@ class ParameterError(AnsibleModuleError):
pass
class Sentinel(object):
def __new__(cls, *args, **kwargs):
return cls
def _ansible_excepthook(exc_type, exc_value, tb):
# Using an exception allows us to catch it if the calling code knows it can recover
if issubclass(exc_type, AnsibleModuleError):

@ -20,12 +20,12 @@ from __future__ import annotations
import ansible.constants as C
from ansible.errors import AnsibleParserError, AnsibleError, AnsibleAssertionError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_text
from ansible.parsing.splitter import parse_kv, split_args
from ansible.plugins.loader import module_loader, action_loader
from ansible.template import Templar
from ansible.utils.fqcn import add_internal_fqcns
from ansible.utils.sentinel import Sentinel
# modules formated for user msg

@ -17,7 +17,7 @@
from __future__ import annotations
from ansible.utils.sentinel import Sentinel
from ansible.module_utils.common.sentinel import Sentinel
_CONTAINERS = frozenset(('list', 'dict', 'set'))

@ -19,13 +19,13 @@ from ansible import context
from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError
from ansible.module_utils.six import string_types
from ansible.module_utils.parsing.convert_bool import boolean
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_text
from ansible.parsing.dataloader import DataLoader
from ansible.playbook.attribute import Attribute, FieldAttribute, ConnectionFieldAttribute, NonInheritableFieldAttribute
from ansible.plugins.loader import module_loader, action_loader
from ansible.utils.collection_loader._collection_finder import _get_collection_metadata, AnsibleCollectionRef
from ansible.utils.display import Display
from ansible.utils.sentinel import Sentinel
from ansible.utils.vars import combine_vars, isidentifier, get_unique_id
display = Display()

@ -19,6 +19,7 @@ from __future__ import annotations
import ansible.constants as C
from ansible.errors import AnsibleParserError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.playbook.attribute import NonInheritableFieldAttribute
from ansible.playbook.base import Base
from ansible.playbook.conditional import Conditional
@ -28,7 +29,6 @@ from ansible.playbook.helpers import load_list_of_tasks
from ansible.playbook.notifiable import Notifiable
from ansible.playbook.role import Role
from ansible.playbook.taggable import Taggable
from ansible.utils.sentinel import Sentinel
class Block(Base, Conditional, CollectionSearch, Taggable, Notifiable, Delegatable):

@ -24,6 +24,7 @@ from types import MappingProxyType
from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleParserError, AnsibleAssertionError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.six import binary_type, text_type
from ansible.playbook.attribute import FieldAttribute
@ -37,7 +38,6 @@ from ansible.playbook.taggable import Taggable
from ansible.plugins.loader import add_all_plugin_dirs
from ansible.utils.collection_loader import AnsibleCollectionConfig
from ansible.utils.path import is_subpath
from ansible.utils.sentinel import Sentinel
from ansible.utils.vars import combine_vars
__all__ = ['Role', 'hash_params']

@ -19,9 +19,9 @@ from __future__ import annotations
from ansible.errors import AnsibleError
from ansible.module_utils.six import string_types
from ansible.module_utils.common.sentinel import Sentinel
from ansible.playbook.attribute import FieldAttribute
from ansible.template import Templar
from ansible.utils.sentinel import Sentinel
def _flatten_tags(tags: list) -> list:

@ -19,6 +19,7 @@ from __future__ import annotations
from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleParserError, AnsibleUndefinedVariable, AnsibleAssertionError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.six import string_types
from ansible.parsing.mod_args import ModuleArgsParser
@ -36,7 +37,7 @@ from ansible.playbook.role import Role
from ansible.playbook.taggable import Taggable
from ansible.utils.collection_loader import AnsibleCollectionConfig
from ansible.utils.display import Display
from ansible.utils.sentinel import Sentinel
from ansible.utils.vars import isidentifier
__all__ = ['Task']

@ -19,10 +19,10 @@ from __future__ import annotations
import ansible.constants as C
from ansible.errors import AnsibleParserError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.playbook.block import Block
from ansible.playbook.task import Task
from ansible.utils.display import Display
from ansible.utils.sentinel import Sentinel
__all__ = ['TaskInclude']

@ -84,10 +84,10 @@ import ansible.plugins.loader as plugin_loader
from ansible import constants as C
from ansible.errors import AnsibleError, AnsibleLookupError, AnsibleOptionsError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_native
from ansible.module_utils.six import string_types
from ansible.plugins.lookup import LookupBase
from ansible.utils.sentinel import Sentinel
class MissingSetting(AnsibleOptionsError):

@ -41,6 +41,7 @@ from ansible.executor.process.worker import WorkerProcess
from ansible.executor.task_result import TaskResult
from ansible.executor.task_queue_manager import CallbackSend, DisplaySend, PromptSend
from ansible.module_utils.six import string_types
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_text
from ansible.module_utils.connection import Connection, ConnectionError
from ansible.playbook.conditional import Conditional
@ -53,7 +54,6 @@ from ansible.template import Templar
from ansible.utils.display import Display
from ansible.utils.fqcn import add_internal_fqcns
from ansible.utils.unsafe_proxy import wrap_var
from ansible.utils.sentinel import Sentinel
from ansible.utils.vars import combine_vars
from ansible.vars.clean import strip_internal_keys, module_response_deepcopy

@ -1,66 +1,8 @@
# Copyright (c) 2019 Ansible Project
# -*- coding: utf-8 -*-
# Copyright: Contributors to the Ansible project
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import annotations
class Sentinel:
"""
Object which can be used to mark whether an entry as being special
A sentinel value demarcates a value or marks an entry as having a special meaning. In C, the
Null byte is used as a sentinel for the end of a string. In Python, None is often used as
a Sentinel in optional parameters to mean that the parameter was not set by the user.
You should use None as a Sentinel value any Python code where None is not a valid entry. If
None is a valid entry, though, then you need to create a different value, which is the purpose
of this class.
Example of using Sentinel as a default parameter value::
def confirm_big_red_button(tristate=Sentinel):
if tristate is Sentinel:
print('You must explicitly press the big red button to blow up the base')
elif tristate is True:
print('Countdown to destruction activated')
elif tristate is False:
print('Countdown stopped')
elif tristate is None:
print('Waiting for more input')
Example of using Sentinel to tell whether a dict which has a default value has been changed::
values = {'one': Sentinel, 'two': Sentinel}
defaults = {'one': 1, 'two': 2}
# [.. Other code which does things including setting a new value for 'one' ..]
values['one'] = None
# [..]
print('You made changes to:')
for key, value in values.items():
if value is Sentinel:
continue
print('%s: %s' % (key, value)
"""
def __new__(cls):
"""
Return the cls itself. This makes both equality and identity True for comparing the class
to an instance of the class, preventing common usage errors.
Preferred usage::
a = Sentinel
if a is Sentinel:
print('Sentinel value')
However, these are True as well, eliminating common usage errors::
if Sentinel is Sentinel():
print('Sentinel value')
if Sentinel == Sentinel():
print('Sentinel value')
"""
return cls
# For Backward compatibility
from ansible.module_utils.common.sentinel import Sentinel # pylint: disable=unused-import

@ -22,13 +22,13 @@ from ansible.cli.galaxy import GalaxyCLI
from ansible.config import manager
from ansible.errors import AnsibleError
from ansible.galaxy import api, collection, token
from ansible.module_utils.common.sentinel import Sentinel
from ansible.module_utils.common.text.converters import to_bytes, to_native, to_text
from ansible.module_utils.common.file import S_IRWU_RG_RO
import builtins
from ansible.utils import context_objects as co
from ansible.utils.display import Display
from ansible.utils.hashing import secure_hash_s
from ansible.utils.sentinel import Sentinel
@pytest.fixture(autouse='function')

@ -7,9 +7,9 @@ from __future__ import annotations
import pytest
from ansible.errors import AnsibleParserError
from ansible.module_utils.common.sentinel import Sentinel
from ansible.parsing.mod_args import ModuleArgsParser
from ansible.plugins.loader import init_plugin_loader
from ansible.utils.sentinel import Sentinel
class TestModArgsDwim:

Loading…
Cancel
Save