summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAbhijeet Kasurde <akasurde@redhat.com>2024-10-03 00:49:35 +0200
committerGitHub <noreply@github.com>2024-10-03 00:49:35 +0200
commitb3c4154e86e4059d6baafc7d0f4a791ba95a9b51 (patch)
treed1cd048c4be335f064b60ede1907c853e009dec1
parentansible-test - Update nios-test-container to 6.0.0 (#84042) (diff)
downloadansible-b3c4154e86e4059d6baafc7d0f4a791ba95a9b51.tar.xz
ansible-b3c4154e86e4059d6baafc7d0f4a791ba95a9b51.zip
Use sentinel everywhere (#84041)
* Use sentinel everywhere Signed-off-by: Abhijeet Kasurde <akasurde@redhat.com>
-rw-r--r--lib/ansible/config/manager.py11
-rw-r--r--lib/ansible/galaxy/collection/__init__.py2
-rw-r--r--lib/ansible/galaxy/collection/concrete_artifact_manager.py2
-rw-r--r--lib/ansible/galaxy/token.py7
-rw-r--r--lib/ansible/module_utils/common/sentinel.py66
-rw-r--r--lib/ansible/modules/file.py7
-rw-r--r--lib/ansible/parsing/mod_args.py2
-rw-r--r--lib/ansible/playbook/attribute.py2
-rw-r--r--lib/ansible/playbook/base.py2
-rw-r--r--lib/ansible/playbook/block.py2
-rw-r--r--lib/ansible/playbook/role/__init__.py2
-rw-r--r--lib/ansible/playbook/taggable.py2
-rw-r--r--lib/ansible/playbook/task.py3
-rw-r--r--lib/ansible/playbook/task_include.py2
-rw-r--r--lib/ansible/plugins/lookup/config.py2
-rw-r--r--lib/ansible/plugins/strategy/__init__.py2
-rw-r--r--lib/ansible/utils/sentinel.py66
-rw-r--r--test/units/galaxy/test_collection.py2
-rw-r--r--test/units/parsing/test_mod_args.py2
19 files changed, 92 insertions, 94 deletions
diff --git a/lib/ansible/config/manager.py b/lib/ansible/config/manager.py
index e4e7b6a8e9..4bbd9cbf9d 100644
--- a/lib/ansible/config/manager.py
+++ b/lib/ansible/config/manager.py
@@ -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")
diff --git a/lib/ansible/galaxy/collection/__init__.py b/lib/ansible/galaxy/collection/__init__.py
index b2c83ee8c3..829f7aa19d 100644
--- a/lib/ansible/galaxy/collection/__init__.py
+++ b/lib/ansible/galaxy/collection/__init__.py
@@ -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()
diff --git a/lib/ansible/galaxy/collection/concrete_artifact_manager.py b/lib/ansible/galaxy/collection/concrete_artifact_manager.py
index 06c1cf6f93..7ff6b31a10 100644
--- a/lib/ansible/galaxy/collection/concrete_artifact_manager.py
+++ b/lib/ansible/galaxy/collection/concrete_artifact_manager.py
@@ -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
diff --git a/lib/ansible/galaxy/token.py b/lib/ansible/galaxy/token.py
index 573d1b3a56..eb06a34181 100644
--- a/lib/ansible/galaxy/token.py
+++ b/lib/ansible/galaxy/token.py
@@ -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.
diff --git a/lib/ansible/module_utils/common/sentinel.py b/lib/ansible/module_utils/common/sentinel.py
new file mode 100644
index 0000000000..0fdbf4ce31
--- /dev/null
+++ b/lib/ansible/module_utils/common/sentinel.py
@@ -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
diff --git a/lib/ansible/modules/file.py b/lib/ansible/modules/file.py
index ba901404a2..e2c1533313 100644
--- a/lib/ansible/modules/file.py
+++ b/lib/ansible/modules/file.py
@@ -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):
diff --git a/lib/ansible/parsing/mod_args.py b/lib/ansible/parsing/mod_args.py
index cfa9574ede..b4956bc3f9 100644
--- a/lib/ansible/parsing/mod_args.py
+++ b/lib/ansible/parsing/mod_args.py
@@ -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
diff --git a/lib/ansible/playbook/attribute.py b/lib/ansible/playbook/attribute.py
index bf3975548a..ee797c27ef 100644
--- a/lib/ansible/playbook/attribute.py
+++ b/lib/ansible/playbook/attribute.py
@@ -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'))
diff --git a/lib/ansible/playbook/base.py b/lib/ansible/playbook/base.py
index 46483efda2..729344a205 100644
--- a/lib/ansible/playbook/base.py
+++ b/lib/ansible/playbook/base.py
@@ -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()
diff --git a/lib/ansible/playbook/block.py b/lib/ansible/playbook/block.py
index 9c82ed2790..fa8c13ee49 100644
--- a/lib/ansible/playbook/block.py
+++ b/lib/ansible/playbook/block.py
@@ -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):
diff --git a/lib/ansible/playbook/role/__init__.py b/lib/ansible/playbook/role/__init__.py
index c37f4be6db..05e6bef044 100644
--- a/lib/ansible/playbook/role/__init__.py
+++ b/lib/ansible/playbook/role/__init__.py
@@ -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']
diff --git a/lib/ansible/playbook/taggable.py b/lib/ansible/playbook/taggable.py
index fa1d5b203f..3b481270a6 100644
--- a/lib/ansible/playbook/taggable.py
+++ b/lib/ansible/playbook/taggable.py
@@ -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:
diff --git a/lib/ansible/playbook/task.py b/lib/ansible/playbook/task.py
index 431501b4af..d42e1df77e 100644
--- a/lib/ansible/playbook/task.py
+++ b/lib/ansible/playbook/task.py
@@ -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']
diff --git a/lib/ansible/playbook/task_include.py b/lib/ansible/playbook/task_include.py
index 4f354cae5f..94f57e5326 100644
--- a/lib/ansible/playbook/task_include.py
+++ b/lib/ansible/playbook/task_include.py
@@ -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']
diff --git a/lib/ansible/plugins/lookup/config.py b/lib/ansible/plugins/lookup/config.py
index 093c1a5003..b31cb057ef 100644
--- a/lib/ansible/plugins/lookup/config.py
+++ b/lib/ansible/plugins/lookup/config.py
@@ -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):
diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py
index 1d8af83361..70073224a4 100644
--- a/lib/ansible/plugins/strategy/__init__.py
+++ b/lib/ansible/plugins/strategy/__init__.py
@@ -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
diff --git a/lib/ansible/utils/sentinel.py b/lib/ansible/utils/sentinel.py
index 0fdbf4ce31..6aa21a17a2 100644
--- a/lib/ansible/utils/sentinel.py
+++ b/lib/ansible/utils/sentinel.py
@@ -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
diff --git a/test/units/galaxy/test_collection.py b/test/units/galaxy/test_collection.py
index 63bc55dae3..bfabd81d9e 100644
--- a/test/units/galaxy/test_collection.py
+++ b/test/units/galaxy/test_collection.py
@@ -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')
diff --git a/test/units/parsing/test_mod_args.py b/test/units/parsing/test_mod_args.py
index 0bb0c954da..472b5465e8 100644
--- a/test/units/parsing/test_mod_args.py
+++ b/test/units/parsing/test_mod_args.py
@@ -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: