File: _utils.py

package info (click to toggle)
ansible-core 2.19.0~beta6-1
  • links: PTS, VCS
  • area: main
  • in suites: trixie
  • size: 32,628 kB
  • sloc: python: 180,313; cs: 4,929; sh: 4,601; xml: 34; makefile: 21
file content (107 lines) | stat: -rw-r--r-- 3,711 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
from __future__ import annotations

import dataclasses
import typing as t

from ansible.module_utils._internal import _ambient_context, _datatag

if t.TYPE_CHECKING:
    from ._engine import TemplateEngine, TemplateOptions


@dataclasses.dataclass(kw_only=True, slots=True, frozen=True)
class LazyOptions:
    """Templating options that apply to lazy containers, which are inherited by descendent lazy containers."""

    DEFAULT: t.ClassVar[t.Self]
    """A shared instance with the default options to minimize instance creation for arg defaults."""
    SKIP_TEMPLATES: t.ClassVar[t.Self]
    """A shared instance with only `template=False` set to minimize instance creation for arg defaults."""
    SKIP_TEMPLATES_AND_ACCESS: t.ClassVar[t.Self]
    """A shared instance with both `template=False` and `access=False` set to minimize instance creation for arg defaults."""

    template: bool = True
    """Enable/disable templating."""

    access: bool = True
    """Enable/disables access calls."""

    unmask_type_names: frozenset[str] = frozenset()
    """Disables template transformations for the provided type names."""


LazyOptions.DEFAULT = LazyOptions()
LazyOptions.SKIP_TEMPLATES = LazyOptions(template=False)
LazyOptions.SKIP_TEMPLATES_AND_ACCESS = LazyOptions(template=False, access=False)


class TemplateContext(_ambient_context.AmbientContextBase):
    def __init__(
        self,
        *,
        template_value: t.Any,
        templar: TemplateEngine,
        options: TemplateOptions,
        stop_on_template: bool = False,
        _render_jinja_const_template: bool = False,
    ):
        self._template_value = template_value
        self._templar = templar
        self._options = options
        self._stop_on_template = stop_on_template
        self._parent_ctx = TemplateContext.current(optional=True)
        self._render_jinja_const_template = _render_jinja_const_template

    @property
    def is_top_level(self) -> bool:
        return not self._parent_ctx

    @property
    def template_value(self) -> t.Any:
        return self._template_value

    @property
    def templar(self) -> TemplateEngine:
        return self._templar

    @property
    def options(self) -> TemplateOptions:
        return self._options

    @property
    def stop_on_template(self) -> bool:
        return self._stop_on_template


class _OmitType:
    """
    A placeholder singleton used to dynamically omit items from a dict/list/tuple/set when the value is `Omit`.

    The `Omit` singleton is accessible from all Ansible templating contexts via the Jinja global name `omit`.
    The `Omit` placeholder value will be visible to Jinja plugins during templating.
    Jinja plugins requiring omit behavior are responsible for handling encountered `Omit` values.
    `Omit` values remaining in template results will be automatically dropped during template finalization.
    When a finalized template renders to a scalar `Omit`, `AnsibleValueOmittedError` will be raised.
    Passing a value other than `Omit` for `value_for_omit` to the `template` call allows that value to be substituted instead of raising.
    """

    __slots__ = ()

    def __new__(cls):
        return Omit

    def __repr__(self):
        return "<<Omit>>"


Omit = object.__new__(_OmitType)

_datatag._untaggable_types.add(_OmitType)


# DTFIX5: review these type sets to ensure they're not overly permissive/dynamic
IGNORE_SCALAR_VAR_TYPES = {value for value in _datatag._ANSIBLE_ALLOWED_SCALAR_VAR_TYPES if not issubclass(value, str)}

PASS_THROUGH_SCALAR_VAR_TYPES = _datatag._ANSIBLE_ALLOWED_SCALAR_VAR_TYPES | {
    _OmitType,  # allow pass through of omit for later handling after top-level finalize completes
}