ansible-core 2.19.2__py3-none-any.whl → 2.20.0b1__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.

Potentially problematic release.


This version of ansible-core might be problematic. Click here for more details.

Files changed (202) hide show
  1. ansible/_internal/__init__.py +1 -4
  2. ansible/_internal/_ansiballz/_builder.py +1 -3
  3. ansible/_internal/_collection_proxy.py +7 -9
  4. ansible/_internal/_display_utils.py +145 -0
  5. ansible/_internal/_json/__init__.py +3 -4
  6. ansible/_internal/_templating/_engine.py +1 -1
  7. ansible/_internal/_templating/_jinja_plugins.py +1 -2
  8. ansible/_internal/_wrapt.py +105 -301
  9. ansible/cli/__init__.py +11 -10
  10. ansible/cli/adhoc.py +1 -2
  11. ansible/cli/arguments/option_helpers.py +1 -1
  12. ansible/cli/config.py +5 -6
  13. ansible/cli/doc.py +67 -67
  14. ansible/cli/galaxy.py +15 -24
  15. ansible/cli/inventory.py +0 -1
  16. ansible/cli/playbook.py +0 -1
  17. ansible/cli/pull.py +0 -1
  18. ansible/cli/scripts/ansible_connection_cli_stub.py +1 -1
  19. ansible/config/base.yml +1 -25
  20. ansible/config/manager.py +0 -2
  21. ansible/executor/play_iterator.py +42 -20
  22. ansible/executor/playbook_executor.py +0 -9
  23. ansible/executor/powershell/async_watchdog.ps1 +24 -4
  24. ansible/executor/task_executor.py +32 -22
  25. ansible/executor/task_queue_manager.py +1 -3
  26. ansible/galaxy/api.py +33 -80
  27. ansible/galaxy/collection/__init__.py +4 -17
  28. ansible/galaxy/dependency_resolution/dataclasses.py +0 -10
  29. ansible/galaxy/dependency_resolution/providers.py +1 -2
  30. ansible/galaxy/role.py +1 -33
  31. ansible/inventory/manager.py +2 -3
  32. ansible/keyword_desc.yml +0 -3
  33. ansible/module_utils/_internal/_datatag/__init__.py +2 -10
  34. ansible/module_utils/_internal/_no_six.py +86 -0
  35. ansible/module_utils/_text.py +28 -8
  36. ansible/module_utils/ansible_release.py +2 -2
  37. ansible/module_utils/basic.py +27 -24
  38. ansible/module_utils/common/_collections_compat.py +11 -2
  39. ansible/module_utils/common/collections.py +8 -3
  40. ansible/module_utils/common/dict_transformations.py +1 -2
  41. ansible/module_utils/common/network.py +4 -2
  42. ansible/module_utils/common/parameters.py +32 -41
  43. ansible/module_utils/common/text/converters.py +109 -23
  44. ansible/module_utils/common/text/formatters.py +6 -2
  45. ansible/module_utils/common/validation.py +11 -9
  46. ansible/module_utils/connection.py +8 -3
  47. ansible/module_utils/facts/hardware/linux.py +23 -7
  48. ansible/module_utils/facts/hardware/netbsd.py +1 -1
  49. ansible/module_utils/facts/hardware/sunos.py +2 -1
  50. ansible/module_utils/facts/packages.py +6 -2
  51. ansible/module_utils/facts/system/distribution.py +2 -1
  52. ansible/module_utils/facts/system/env.py +6 -3
  53. ansible/module_utils/facts/system/local.py +3 -1
  54. ansible/module_utils/parsing/convert_bool.py +6 -2
  55. ansible/module_utils/service.py +2 -3
  56. ansible/module_utils/six/__init__.py +11 -6
  57. ansible/module_utils/urls.py +6 -2
  58. ansible/module_utils/yumdnf.py +0 -5
  59. ansible/modules/apt.py +18 -13
  60. ansible/modules/apt_repository.py +1 -1
  61. ansible/modules/assemble.py +5 -9
  62. ansible/modules/blockinfile.py +39 -23
  63. ansible/modules/cron.py +26 -35
  64. ansible/modules/deb822_repository.py +83 -12
  65. ansible/modules/dnf.py +3 -7
  66. ansible/modules/dnf5.py +4 -6
  67. ansible/modules/expect.py +0 -3
  68. ansible/modules/find.py +1 -2
  69. ansible/modules/get_url.py +1 -1
  70. ansible/modules/git.py +4 -5
  71. ansible/modules/include_vars.py +1 -1
  72. ansible/modules/lineinfile.py +71 -63
  73. ansible/modules/package_facts.py +1 -1
  74. ansible/modules/pip.py +8 -2
  75. ansible/modules/replace.py +6 -6
  76. ansible/modules/service.py +3 -4
  77. ansible/modules/stat.py +20 -0
  78. ansible/modules/uri.py +9 -10
  79. ansible/modules/user.py +1 -2
  80. ansible/modules/wait_for.py +2 -2
  81. ansible/modules/wait_for_connection.py +2 -1
  82. ansible/modules/yum_repository.py +1 -16
  83. ansible/parsing/dataloader.py +24 -31
  84. ansible/parsing/mod_args.py +3 -0
  85. ansible/parsing/vault/__init__.py +1 -2
  86. ansible/playbook/base.py +8 -56
  87. ansible/playbook/block.py +0 -60
  88. ansible/playbook/collectionsearch.py +1 -2
  89. ansible/playbook/handler.py +1 -7
  90. ansible/playbook/helpers.py +0 -7
  91. ansible/playbook/included_file.py +1 -1
  92. ansible/playbook/play.py +103 -37
  93. ansible/playbook/play_context.py +4 -0
  94. ansible/playbook/role/__init__.py +10 -65
  95. ansible/playbook/role/definition.py +3 -4
  96. ansible/playbook/role/include.py +2 -3
  97. ansible/playbook/role/metadata.py +1 -12
  98. ansible/playbook/role/requirement.py +1 -2
  99. ansible/playbook/role_include.py +1 -2
  100. ansible/playbook/taggable.py +16 -5
  101. ansible/playbook/task.py +51 -55
  102. ansible/plugins/action/__init__.py +20 -19
  103. ansible/plugins/action/add_host.py +1 -2
  104. ansible/plugins/action/fetch.py +2 -4
  105. ansible/plugins/action/group_by.py +1 -2
  106. ansible/plugins/action/include_vars.py +20 -22
  107. ansible/plugins/action/script.py +1 -3
  108. ansible/plugins/action/template.py +1 -2
  109. ansible/plugins/action/uri.py +4 -2
  110. ansible/plugins/cache/__init__.py +1 -0
  111. ansible/plugins/callback/__init__.py +13 -6
  112. ansible/plugins/connection/__init__.py +3 -7
  113. ansible/plugins/connection/local.py +2 -3
  114. ansible/plugins/connection/psrp.py +0 -2
  115. ansible/plugins/connection/ssh.py +2 -7
  116. ansible/plugins/connection/winrm.py +0 -2
  117. ansible/plugins/doc_fragments/result_format_callback.py +15 -0
  118. ansible/plugins/filter/core.py +4 -5
  119. ansible/plugins/filter/encryption.py +3 -27
  120. ansible/plugins/filter/mathstuff.py +1 -2
  121. ansible/plugins/filter/to_nice_yaml.yml +31 -3
  122. ansible/plugins/filter/to_yaml.yml +29 -12
  123. ansible/plugins/inventory/__init__.py +1 -2
  124. ansible/plugins/inventory/script.py +2 -1
  125. ansible/plugins/inventory/toml.py +3 -6
  126. ansible/plugins/inventory/yaml.py +1 -2
  127. ansible/plugins/list.py +10 -3
  128. ansible/plugins/loader.py +6 -6
  129. ansible/plugins/lookup/password.py +1 -2
  130. ansible/plugins/lookup/subelements.py +2 -3
  131. ansible/plugins/lookup/url.py +1 -1
  132. ansible/plugins/lookup/varnames.py +1 -2
  133. ansible/plugins/shell/__init__.py +9 -4
  134. ansible/plugins/shell/powershell.py +8 -24
  135. ansible/plugins/strategy/__init__.py +6 -3
  136. ansible/plugins/test/core.py +4 -1
  137. ansible/plugins/test/regex.yml +18 -6
  138. ansible/release.py +2 -2
  139. ansible/template/__init__.py +3 -7
  140. ansible/utils/collection_loader/_collection_config.py +5 -0
  141. ansible/utils/collection_loader/_collection_finder.py +11 -14
  142. ansible/utils/context_objects.py +7 -4
  143. ansible/utils/display.py +28 -167
  144. ansible/utils/encrypt.py +0 -5
  145. ansible/utils/helpers.py +6 -2
  146. ansible/utils/jsonrpc.py +7 -3
  147. ansible/utils/plugin_docs.py +49 -38
  148. ansible/utils/ssh_functions.py +0 -19
  149. ansible/utils/unsafe_proxy.py +7 -7
  150. ansible/vars/clean.py +2 -3
  151. ansible/vars/manager.py +27 -20
  152. ansible/vars/plugins.py +1 -31
  153. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/METADATA +3 -3
  154. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/RECORD +200 -200
  155. ansible_test/_data/completion/docker.txt +7 -7
  156. ansible_test/_data/completion/network.txt +0 -1
  157. ansible_test/_data/completion/remote.txt +4 -4
  158. ansible_test/_data/requirements/ansible-test.txt +1 -1
  159. ansible_test/_data/requirements/sanity.changelog.txt +1 -1
  160. ansible_test/_data/requirements/sanity.pep8.txt +1 -1
  161. ansible_test/_data/requirements/sanity.pylint.txt +4 -4
  162. ansible_test/_internal/cache.py +2 -5
  163. ansible_test/_internal/cli/compat.py +1 -1
  164. ansible_test/_internal/commands/coverage/combine.py +1 -3
  165. ansible_test/_internal/commands/integration/__init__.py +3 -7
  166. ansible_test/_internal/commands/integration/cloud/httptester.py +1 -1
  167. ansible_test/_internal/commands/integration/coverage.py +1 -3
  168. ansible_test/_internal/commands/integration/filters.py +5 -10
  169. ansible_test/_internal/commands/sanity/validate_modules.py +1 -5
  170. ansible_test/_internal/commands/units/__init__.py +1 -13
  171. ansible_test/_internal/completion.py +2 -5
  172. ansible_test/_internal/config.py +2 -7
  173. ansible_test/_internal/coverage_util.py +1 -1
  174. ansible_test/_internal/delegation.py +2 -0
  175. ansible_test/_internal/docker_util.py +1 -1
  176. ansible_test/_internal/host_profiles.py +6 -11
  177. ansible_test/_internal/provider/__init__.py +2 -5
  178. ansible_test/_internal/provisioning.py +2 -5
  179. ansible_test/_internal/pypi_proxy.py +1 -1
  180. ansible_test/_internal/target.py +2 -6
  181. ansible_test/_internal/thread.py +1 -4
  182. ansible_test/_internal/util.py +9 -14
  183. ansible_test/_util/controller/sanity/code-smell/runtime-metadata.py +14 -19
  184. ansible_test/_util/controller/sanity/pylint/plugins/unwanted.py +30 -27
  185. ansible_test/_util/controller/sanity/validate-modules/validate_modules/main.py +31 -18
  186. ansible_test/_util/controller/sanity/validate-modules/validate_modules/module_args.py +1 -2
  187. ansible_test/_util/controller/sanity/validate-modules/validate_modules/schema.py +59 -71
  188. ansible_test/_util/controller/sanity/validate-modules/validate_modules/utils.py +1 -2
  189. ansible_test/_util/target/cli/ansible_test_cli_stub.py +4 -2
  190. ansible_test/_util/target/common/constants.py +2 -2
  191. ansible_test/_util/target/setup/bootstrap.sh +0 -6
  192. ansible/utils/py3compat.py +0 -27
  193. ansible_test/_data/pytest/config/legacy.ini +0 -4
  194. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/WHEEL +0 -0
  195. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/entry_points.txt +0 -0
  196. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/COPYING +0 -0
  197. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/Apache-License.txt +0 -0
  198. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/BSD-3-Clause.txt +0 -0
  199. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/MIT-license.txt +0 -0
  200. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/PSF-license.txt +0 -0
  201. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/licenses/licenses/simplified_bsd.txt +0 -0
  202. {ansible_core-2.19.2.dist-info → ansible_core-2.20.0b1.dist-info}/top_level.txt +0 -0
@@ -23,7 +23,7 @@
23
23
  # ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
24
24
  # POSSIBILITY OF SUCH DAMAGE.
25
25
 
26
- # copied from https://github.com/GrahamDumpleton/wrapt/blob/1.15.0/src/wrapt/wrappers.py
26
+ # copied from https://github.com/GrahamDumpleton/wrapt/blob/1.17.2/src/wrapt/wrappers.py
27
27
 
28
28
  # LOCAL PATCHES:
29
29
  # - disabled optional relative import of the _wrappers C extension; we shouldn't need it
@@ -31,13 +31,10 @@
31
31
  from __future__ import annotations
32
32
 
33
33
  # The following makes it easier for us to script updates of the bundled code
34
- _BUNDLED_METADATA = {"pypi_name": "wrapt", "version": "1.15.0"}
34
+ _BUNDLED_METADATA = {"pypi_name": "wrapt", "version": "1.17.2"}
35
35
 
36
- import os
37
36
  import sys
38
- import functools
39
37
  import operator
40
- import weakref
41
38
  import inspect
42
39
 
43
40
  PY2 = sys.version_info[0] == 2
@@ -129,6 +126,9 @@ class ObjectProxy(with_metaclass(_ObjectProxyMetaType)):
129
126
  except AttributeError:
130
127
  pass
131
128
 
129
+ def __self_setattr__(self, name, value):
130
+ object.__setattr__(self, name, value)
131
+
132
132
  @property
133
133
  def __name__(self):
134
134
  return self.__wrapped__.__name__
@@ -161,12 +161,15 @@ class ObjectProxy(with_metaclass(_ObjectProxyMetaType)):
161
161
  type(self.__wrapped__).__name__,
162
162
  id(self.__wrapped__))
163
163
 
164
+ def __format__(self, format_spec):
165
+ return format(self.__wrapped__, format_spec)
166
+
164
167
  def __reversed__(self):
165
168
  return reversed(self.__wrapped__)
166
169
 
167
170
  if not PY2:
168
- def __round__(self):
169
- return round(self.__wrapped__)
171
+ def __round__(self, ndigits=None):
172
+ return round(self.__wrapped__, ndigits)
170
173
 
171
174
  if sys.hexversion >= 0x03070000:
172
175
  def __mro_entries__(self, bases):
@@ -472,7 +475,7 @@ class ObjectProxy(with_metaclass(_ObjectProxyMetaType)):
472
475
 
473
476
  def __reduce__(self):
474
477
  raise NotImplementedError(
475
- 'object proxy must define __reduce_ex__()')
478
+ 'object proxy must define __reduce__()')
476
479
 
477
480
  def __reduce_ex__(self, protocol):
478
481
  raise NotImplementedError(
@@ -525,10 +528,10 @@ class PartialCallableObjectProxy(ObjectProxy):
525
528
  class _FunctionWrapperBase(ObjectProxy):
526
529
 
527
530
  __slots__ = ('_self_instance', '_self_wrapper', '_self_enabled',
528
- '_self_binding', '_self_parent')
531
+ '_self_binding', '_self_parent', '_self_owner')
529
532
 
530
533
  def __init__(self, wrapped, instance, wrapper, enabled=None,
531
- binding='function', parent=None):
534
+ binding='callable', parent=None, owner=None):
532
535
 
533
536
  super(_FunctionWrapperBase, self).__init__(wrapped)
534
537
 
@@ -537,60 +540,68 @@ class _FunctionWrapperBase(ObjectProxy):
537
540
  object.__setattr__(self, '_self_enabled', enabled)
538
541
  object.__setattr__(self, '_self_binding', binding)
539
542
  object.__setattr__(self, '_self_parent', parent)
543
+ object.__setattr__(self, '_self_owner', owner)
540
544
 
541
545
  def __get__(self, instance, owner):
542
- # This method is actually doing double duty for both unbound and
543
- # bound derived wrapper classes. It should possibly be broken up
544
- # and the distinct functionality moved into the derived classes.
545
- # Can't do that straight away due to some legacy code which is
546
- # relying on it being here in this base class.
546
+ # This method is actually doing double duty for both unbound and bound
547
+ # derived wrapper classes. It should possibly be broken up and the
548
+ # distinct functionality moved into the derived classes. Can't do that
549
+ # straight away due to some legacy code which is relying on it being
550
+ # here in this base class.
547
551
  #
548
- # The distinguishing attribute which determines whether we are
549
- # being called in an unbound or bound wrapper is the parent
550
- # attribute. If binding has never occurred, then the parent will
551
- # be None.
552
+ # The distinguishing attribute which determines whether we are being
553
+ # called in an unbound or bound wrapper is the parent attribute. If
554
+ # binding has never occurred, then the parent will be None.
552
555
  #
553
- # First therefore, is if we are called in an unbound wrapper. In
554
- # this case we perform the binding.
556
+ # First therefore, is if we are called in an unbound wrapper. In this
557
+ # case we perform the binding.
555
558
  #
556
- # We have one special case to worry about here. This is where we
557
- # are decorating a nested class. In this case the wrapped class
558
- # would not have a __get__() method to call. In that case we
559
- # simply return self.
559
+ # We have two special cases to worry about here. These are where we are
560
+ # decorating a class or builtin function as neither provide a __get__()
561
+ # method to call. In this case we simply return self.
560
562
  #
561
- # Note that we otherwise still do binding even if instance is
562
- # None and accessing an unbound instance method from a class.
563
- # This is because we need to be able to later detect that
564
- # specific case as we will need to extract the instance from the
565
- # first argument of those passed in.
563
+ # Note that we otherwise still do binding even if instance is None and
564
+ # accessing an unbound instance method from a class. This is because we
565
+ # need to be able to later detect that specific case as we will need to
566
+ # extract the instance from the first argument of those passed in.
566
567
 
567
568
  if self._self_parent is None:
568
- if not inspect.isclass(self.__wrapped__):
569
- descriptor = self.__wrapped__.__get__(instance, owner)
569
+ # Technically can probably just check for existence of __get__ on
570
+ # the wrapped object, but this is more explicit.
571
+
572
+ if self._self_binding == 'builtin':
573
+ return self
570
574
 
571
- return self.__bound_function_wrapper__(descriptor, instance,
572
- self._self_wrapper, self._self_enabled,
573
- self._self_binding, self)
575
+ if self._self_binding == "class":
576
+ return self
574
577
 
575
- return self
578
+ binder = getattr(self.__wrapped__, '__get__', None)
576
579
 
577
- # Now we have the case of binding occurring a second time on what
578
- # was already a bound function. In this case we would usually
579
- # return ourselves again. This mirrors what Python does.
580
+ if binder is None:
581
+ return self
582
+
583
+ descriptor = binder(instance, owner)
584
+
585
+ return self.__bound_function_wrapper__(descriptor, instance,
586
+ self._self_wrapper, self._self_enabled,
587
+ self._self_binding, self, owner)
588
+
589
+ # Now we have the case of binding occurring a second time on what was
590
+ # already a bound function. In this case we would usually return
591
+ # ourselves again. This mirrors what Python does.
580
592
  #
581
- # The special case this time is where we were originally bound
582
- # with an instance of None and we were likely an instance
583
- # method. In that case we rebind against the original wrapped
584
- # function from the parent again.
593
+ # The special case this time is where we were originally bound with an
594
+ # instance of None and we were likely an instance method. In that case
595
+ # we rebind against the original wrapped function from the parent again.
585
596
 
586
- if self._self_instance is None and self._self_binding == 'function':
597
+ if self._self_instance is None and self._self_binding in ('function', 'instancemethod', 'callable'):
587
598
  descriptor = self._self_parent.__wrapped__.__get__(
588
599
  instance, owner)
589
600
 
590
601
  return self._self_parent.__bound_function_wrapper__(
591
602
  descriptor, instance, self._self_wrapper,
592
603
  self._self_enabled, self._self_binding,
593
- self._self_parent)
604
+ self._self_parent, owner)
594
605
 
595
606
  return self
596
607
 
@@ -617,7 +628,7 @@ class _FunctionWrapperBase(ObjectProxy):
617
628
  # a function that was already bound to an instance. In that case
618
629
  # we want to extract the instance from the function and use it.
619
630
 
620
- if self._self_binding in ('function', 'classmethod'):
631
+ if self._self_binding in ('function', 'instancemethod', 'classmethod', 'callable'):
621
632
  if self._self_instance is None:
622
633
  instance = getattr(self.__wrapped__, '__self__', None)
623
634
  if instance is not None:
@@ -668,11 +679,11 @@ class BoundFunctionWrapper(_FunctionWrapperBase):
668
679
 
669
680
  self, args = _unpack_self(*args)
670
681
 
671
- # If enabled has been specified, then evaluate it at this point
672
- # and if the wrapper is not to be executed, then simply return
673
- # the bound function rather than a bound wrapper for the bound
674
- # function. When evaluating enabled, if it is callable we call
675
- # it, otherwise we evaluate it as a boolean.
682
+ # If enabled has been specified, then evaluate it at this point and if
683
+ # the wrapper is not to be executed, then simply return the bound
684
+ # function rather than a bound wrapper for the bound function. When
685
+ # evaluating enabled, if it is callable we call it, otherwise we
686
+ # evaluate it as a boolean.
676
687
 
677
688
  if self._self_enabled is not None:
678
689
  if callable(self._self_enabled):
@@ -681,18 +692,27 @@ class BoundFunctionWrapper(_FunctionWrapperBase):
681
692
  elif not self._self_enabled:
682
693
  return self.__wrapped__(*args, **kwargs)
683
694
 
684
- # We need to do things different depending on whether we are
685
- # likely wrapping an instance method vs a static method or class
686
- # method.
695
+ # We need to do things different depending on whether we are likely
696
+ # wrapping an instance method vs a static method or class method.
687
697
 
688
698
  if self._self_binding == 'function':
699
+ if self._self_instance is None and args:
700
+ instance, newargs = args[0], args[1:]
701
+ if isinstance(instance, self._self_owner):
702
+ wrapped = PartialCallableObjectProxy(self.__wrapped__, instance)
703
+ return self._self_wrapper(wrapped, instance, newargs, kwargs)
704
+
705
+ return self._self_wrapper(self.__wrapped__, self._self_instance,
706
+ args, kwargs)
707
+
708
+ elif self._self_binding == 'callable':
689
709
  if self._self_instance is None:
690
710
  # This situation can occur where someone is calling the
691
- # instancemethod via the class type and passing the instance
692
- # as the first argument. We need to shift the args before
693
- # making the call to the wrapper and effectively bind the
694
- # instance to the wrapped function using a partial so the
695
- # wrapper doesn't see anything as being different.
711
+ # instancemethod via the class type and passing the instance as
712
+ # the first argument. We need to shift the args before making
713
+ # the call to the wrapper and effectively bind the instance to
714
+ # the wrapped function using a partial so the wrapper doesn't
715
+ # see anything as being different.
696
716
 
697
717
  if not args:
698
718
  raise TypeError('missing 1 required positional argument')
@@ -794,259 +814,43 @@ class FunctionWrapper(_FunctionWrapperBase):
794
814
  # or patch it in the __dict__ of the class type.
795
815
  #
796
816
  # So to get the best outcome we can, whenever we aren't sure what
797
- # it is, we label it as a 'function'. If it was already bound and
817
+ # it is, we label it as a 'callable'. If it was already bound and
798
818
  # that is rebound later, we assume that it will be an instance
799
- # method and try an cope with the possibility that the 'self'
819
+ # method and try and cope with the possibility that the 'self'
800
820
  # argument it being passed as an explicit argument and shuffle
801
821
  # the arguments around to extract 'self' for use as the instance.
802
822
 
803
- if isinstance(wrapped, classmethod):
804
- binding = 'classmethod'
805
-
806
- elif isinstance(wrapped, staticmethod):
807
- binding = 'staticmethod'
808
-
809
- elif hasattr(wrapped, '__self__'):
810
- if inspect.isclass(wrapped.__self__):
811
- binding = 'classmethod'
812
- else:
813
- binding = 'function'
814
-
815
- else:
816
- binding = 'function'
817
-
818
- super(FunctionWrapper, self).__init__(wrapped, None, wrapper,
819
- enabled, binding)
820
-
821
- # disabled support for native extension; we likely don't need it
822
- # try:
823
- # if not os.environ.get('WRAPT_DISABLE_EXTENSIONS'):
824
- # from ._wrappers import (ObjectProxy, CallableObjectProxy,
825
- # PartialCallableObjectProxy, FunctionWrapper,
826
- # BoundFunctionWrapper, _FunctionWrapperBase)
827
- # except ImportError:
828
- # pass
829
-
830
- # Helper functions for applying wrappers to existing functions.
831
-
832
- def resolve_path(module, name):
833
- if isinstance(module, string_types):
834
- __import__(module)
835
- module = sys.modules[module]
836
-
837
- parent = module
838
-
839
- path = name.split('.')
840
- attribute = path[0]
841
-
842
- # We can't just always use getattr() because in doing
843
- # that on a class it will cause binding to occur which
844
- # will complicate things later and cause some things not
845
- # to work. For the case of a class we therefore access
846
- # the __dict__ directly. To cope though with the wrong
847
- # class being given to us, or a method being moved into
848
- # a base class, we need to walk the class hierarchy to
849
- # work out exactly which __dict__ the method was defined
850
- # in, as accessing it from __dict__ will fail if it was
851
- # not actually on the class given. Fallback to using
852
- # getattr() if we can't find it. If it truly doesn't
853
- # exist, then that will fail.
854
-
855
- def lookup_attribute(parent, attribute):
856
- if inspect.isclass(parent):
857
- for cls in inspect.getmro(parent):
858
- if attribute in vars(cls):
859
- return vars(cls)[attribute]
860
- else:
861
- return getattr(parent, attribute)
862
- else:
863
- return getattr(parent, attribute)
864
-
865
- original = lookup_attribute(parent, attribute)
866
-
867
- for attribute in path[1:]:
868
- parent = original
869
- original = lookup_attribute(parent, attribute)
870
-
871
- return (parent, attribute, original)
872
-
873
- def apply_patch(parent, attribute, replacement):
874
- setattr(parent, attribute, replacement)
875
-
876
- def wrap_object(module, name, factory, args=(), kwargs={}):
877
- (parent, attribute, original) = resolve_path(module, name)
878
- wrapper = factory(original, *args, **kwargs)
879
- apply_patch(parent, attribute, wrapper)
880
- return wrapper
881
-
882
- # Function for applying a proxy object to an attribute of a class
883
- # instance. The wrapper works by defining an attribute of the same name
884
- # on the class which is a descriptor and which intercepts access to the
885
- # instance attribute. Note that this cannot be used on attributes which
886
- # are themselves defined by a property object.
887
-
888
- class AttributeWrapper(object):
889
-
890
- def __init__(self, attribute, factory, args, kwargs):
891
- self.attribute = attribute
892
- self.factory = factory
893
- self.args = args
894
- self.kwargs = kwargs
895
-
896
- def __get__(self, instance, owner):
897
- value = instance.__dict__[self.attribute]
898
- return self.factory(value, *self.args, **self.kwargs)
899
-
900
- def __set__(self, instance, value):
901
- instance.__dict__[self.attribute] = value
902
-
903
- def __delete__(self, instance):
904
- del instance.__dict__[self.attribute]
905
-
906
- def wrap_object_attribute(module, name, factory, args=(), kwargs={}):
907
- path, attribute = name.rsplit('.', 1)
908
- parent = resolve_path(module, path)[2]
909
- wrapper = AttributeWrapper(attribute, factory, args, kwargs)
910
- apply_patch(parent, attribute, wrapper)
911
- return wrapper
912
-
913
- # Functions for creating a simple decorator using a FunctionWrapper,
914
- # plus short cut functions for applying wrappers to functions. These are
915
- # for use when doing monkey patching. For a more featured way of
916
- # creating decorators see the decorator decorator instead.
917
-
918
- def function_wrapper(wrapper):
919
- def _wrapper(wrapped, instance, args, kwargs):
920
- target_wrapped = args[0]
921
- if instance is None:
922
- target_wrapper = wrapper
923
- elif inspect.isclass(instance):
924
- target_wrapper = wrapper.__get__(None, instance)
925
- else:
926
- target_wrapper = wrapper.__get__(instance, type(instance))
927
- return FunctionWrapper(target_wrapped, target_wrapper)
928
- return FunctionWrapper(wrapper, _wrapper)
929
-
930
- def wrap_function_wrapper(module, name, wrapper):
931
- return wrap_object(module, name, FunctionWrapper, (wrapper,))
932
-
933
- def patch_function_wrapper(module, name):
934
- def _wrapper(wrapper):
935
- return wrap_object(module, name, FunctionWrapper, (wrapper,))
936
- return _wrapper
937
-
938
- def transient_function_wrapper(module, name):
939
- def _decorator(wrapper):
940
- def _wrapper(wrapped, instance, args, kwargs):
941
- target_wrapped = args[0]
942
- if instance is None:
943
- target_wrapper = wrapper
944
- elif inspect.isclass(instance):
945
- target_wrapper = wrapper.__get__(None, instance)
946
- else:
947
- target_wrapper = wrapper.__get__(instance, type(instance))
948
- def _execute(wrapped, instance, args, kwargs):
949
- (parent, attribute, original) = resolve_path(module, name)
950
- replacement = FunctionWrapper(original, target_wrapper)
951
- setattr(parent, attribute, replacement)
952
- try:
953
- return wrapped(*args, **kwargs)
954
- finally:
955
- setattr(parent, attribute, original)
956
- return FunctionWrapper(target_wrapped, _execute)
957
- return FunctionWrapper(wrapper, _wrapper)
958
- return _decorator
959
-
960
- # A weak function proxy. This will work on instance methods, class
961
- # methods, static methods and regular functions. Special treatment is
962
- # needed for the method types because the bound method is effectively a
963
- # transient object and applying a weak reference to one will immediately
964
- # result in it being destroyed and the weakref callback called. The weak
965
- # reference is therefore applied to the instance the method is bound to
966
- # and the original function. The function is then rebound at the point
967
- # of a call via the weak function proxy.
968
-
969
- def _weak_function_proxy_callback(ref, proxy, callback):
970
- if proxy._self_expired:
971
- return
972
-
973
- proxy._self_expired = True
974
-
975
- # This could raise an exception. We let it propagate back and let
976
- # the weakref.proxy() deal with it, at which point it generally
977
- # prints out a short error message direct to stderr and keeps going.
978
-
979
- if callback is not None:
980
- callback(proxy)
981
-
982
- class WeakFunctionProxy(ObjectProxy):
983
-
984
- __slots__ = ('_self_expired', '_self_instance')
985
-
986
- def __init__(self, wrapped, callback=None):
987
- # We need to determine if the wrapped function is actually a
988
- # bound method. In the case of a bound method, we need to keep a
989
- # reference to the original unbound function and the instance.
990
- # This is necessary because if we hold a reference to the bound
991
- # function, it will be the only reference and given it is a
992
- # temporary object, it will almost immediately expire and
993
- # the weakref callback triggered. So what is done is that we
994
- # hold a reference to the instance and unbound function and
995
- # when called bind the function to the instance once again and
996
- # then call it. Note that we avoid using a nested function for
997
- # the callback here so as not to cause any odd reference cycles.
998
-
999
- _callback = callback and functools.partial(
1000
- _weak_function_proxy_callback, proxy=self,
1001
- callback=callback)
1002
-
1003
- self._self_expired = False
823
+ binding = None
1004
824
 
1005
825
  if isinstance(wrapped, _FunctionWrapperBase):
1006
- self._self_instance = weakref.ref(wrapped._self_instance,
1007
- _callback)
826
+ binding = wrapped._self_binding
1008
827
 
1009
- if wrapped._self_parent is not None:
1010
- super(WeakFunctionProxy, self).__init__(
1011
- weakref.proxy(wrapped._self_parent, _callback))
828
+ if not binding:
829
+ if inspect.isbuiltin(wrapped):
830
+ binding = 'builtin'
1012
831
 
1013
- else:
1014
- super(WeakFunctionProxy, self).__init__(
1015
- weakref.proxy(wrapped, _callback))
1016
-
1017
- return
1018
-
1019
- try:
1020
- self._self_instance = weakref.ref(wrapped.__self__, _callback)
1021
-
1022
- super(WeakFunctionProxy, self).__init__(
1023
- weakref.proxy(wrapped.__func__, _callback))
1024
-
1025
- except AttributeError:
1026
- self._self_instance = None
1027
-
1028
- super(WeakFunctionProxy, self).__init__(
1029
- weakref.proxy(wrapped, _callback))
1030
-
1031
- def __call__(*args, **kwargs):
1032
- def _unpack_self(self, *args):
1033
- return self, args
832
+ elif inspect.isfunction(wrapped):
833
+ binding = 'function'
1034
834
 
1035
- self, args = _unpack_self(*args)
835
+ elif inspect.isclass(wrapped):
836
+ binding = 'class'
1036
837
 
1037
- # We perform a boolean check here on the instance and wrapped
1038
- # function as that will trigger the reference error prior to
1039
- # calling if the reference had expired.
838
+ elif isinstance(wrapped, classmethod):
839
+ binding = 'classmethod'
1040
840
 
1041
- instance = self._self_instance and self._self_instance()
1042
- function = self.__wrapped__ and self.__wrapped__
841
+ elif isinstance(wrapped, staticmethod):
842
+ binding = 'staticmethod'
1043
843
 
1044
- # If the wrapped function was originally a bound function, for
1045
- # which we retained a reference to the instance and the unbound
1046
- # function we need to rebind the function and then call it. If
1047
- # not just called the wrapped function.
844
+ elif hasattr(wrapped, '__self__'):
845
+ if inspect.isclass(wrapped.__self__):
846
+ binding = 'classmethod'
847
+ elif inspect.ismethod(wrapped):
848
+ binding = 'instancemethod'
849
+ else:
850
+ binding = 'callable'
1048
851
 
1049
- if instance is None:
1050
- return self.__wrapped__(*args, **kwargs)
852
+ else:
853
+ binding = 'callable'
1051
854
 
1052
- return function.__get__(instance, type(instance))(*args, **kwargs)
855
+ super(FunctionWrapper, self).__init__(wrapped, None, wrapper,
856
+ enabled, binding)
ansible/cli/__init__.py CHANGED
@@ -23,10 +23,12 @@ if 1 <= len(sys.argv) <= 2 and os.path.basename(sys.argv[0]) == "ansible" and os
23
23
 
24
24
  # Used for determining if the system is running a new enough python version
25
25
  # and should only restrict on our documented minimum versions
26
- if sys.version_info < (3, 11):
26
+ _PY_MIN = (3, 12)
27
+
28
+ if sys.version_info < _PY_MIN:
27
29
  raise SystemExit(
28
- 'ERROR: Ansible requires Python 3.11 or newer on the controller. '
29
- 'Current version: %s' % ''.join(sys.version.splitlines())
30
+ f"ERROR: Ansible requires Python {'.'.join(map(str, _PY_MIN))} or newer on the controller. "
31
+ f"Current version: {''.join(sys.version.splitlines())}"
30
32
  )
31
33
 
32
34
 
@@ -105,7 +107,6 @@ from ansible import context
105
107
  from ansible.utils import display as _display
106
108
  from ansible.cli.arguments import option_helpers as opt_help
107
109
  from ansible.inventory.manager import InventoryManager
108
- from ansible.module_utils.six import string_types
109
110
  from ansible.module_utils.common.text.converters import to_bytes, to_text
110
111
  from ansible.module_utils.common.collections import is_sequence
111
112
  from ansible.module_utils.common.file import is_executable
@@ -371,7 +372,7 @@ class CLI(ABC):
371
372
  return op
372
373
 
373
374
  @abstractmethod
374
- def init_parser(self, usage="", desc=None, epilog=None):
375
+ def init_parser(self, desc=None, epilog=None):
375
376
  """
376
377
  Create an options parser for most ansible scripts
377
378
 
@@ -381,11 +382,11 @@ class CLI(ABC):
381
382
  An implementation will look something like this::
382
383
 
383
384
  def init_parser(self):
384
- super(MyCLI, self).init_parser(usage="My Ansible CLI", inventory_opts=True)
385
+ super(MyCLI, self).init_parser(desc='The purpose of the program is...')
385
386
  ansible.arguments.option_helpers.add_runas_options(self.parser)
386
387
  self.parser.add_option('--my-option', dest='my_option', action='store')
387
388
  """
388
- self.parser = opt_help.create_base_parser(self.name, usage=usage, desc=desc, epilog=epilog)
389
+ self.parser = opt_help.create_base_parser(self.name, desc=desc, epilog=epilog)
389
390
 
390
391
  @abstractmethod
391
392
  def post_process_args(self, options):
@@ -401,8 +402,8 @@ class CLI(ABC):
401
402
  options = super(MyCLI, self).post_process_args(options)
402
403
  if options.addition and options.subtraction:
403
404
  raise AnsibleOptionsError('Only one of --addition and --subtraction can be specified')
404
- if isinstance(options.listofhosts, string_types):
405
- options.listofhosts = string_types.split(',')
405
+ if isinstance(options.listofhosts, str):
406
+ options.listofhosts = options.listofhosts.split(',')
406
407
  return options
407
408
  """
408
409
 
@@ -438,7 +439,7 @@ class CLI(ABC):
438
439
  if options.inventory:
439
440
 
440
441
  # should always be list
441
- if isinstance(options.inventory, string_types):
442
+ if isinstance(options.inventory, str):
442
443
  options.inventory = [options.inventory]
443
444
 
444
445
  # Ensure full paths when needed
ansible/cli/adhoc.py CHANGED
@@ -37,8 +37,7 @@ class AdHocCLI(CLI):
37
37
 
38
38
  def init_parser(self):
39
39
  """ create an options parser for bin/ansible """
40
- super(AdHocCLI, self).init_parser(usage='%prog <host-pattern> [options]',
41
- desc="Define and run a single task 'playbook' against a set of hosts",
40
+ super(AdHocCLI, self).init_parser(desc="Define and run a single task 'playbook' against a set of hosts",
42
41
  epilog="Some actions do not make sense in Ad-Hoc (include, meta, etc)")
43
42
 
44
43
  opt_help.add_runas_options(self.parser)
@@ -322,7 +322,7 @@ def version(prog=None):
322
322
  # Functions to add pre-canned options to an OptionParser
323
323
  #
324
324
 
325
- def create_base_parser(prog, usage="", desc=None, epilog=None):
325
+ def create_base_parser(prog, desc=None, epilog=None):
326
326
  """
327
327
  Create an options parser for all ansible scripts
328
328
  """
ansible/cli/config.py CHANGED
@@ -24,7 +24,6 @@ from ansible.config.manager import ConfigManager
24
24
  from ansible.errors import AnsibleError, AnsibleOptionsError, AnsibleRequiredOptionError
25
25
  from ansible.module_utils.common.text.converters import to_native, to_text, to_bytes
26
26
  from ansible._internal import _json
27
- from ansible.module_utils.six import string_types
28
27
  from ansible.parsing.quoting import is_quoted
29
28
  from ansible.parsing.yaml.dumper import AnsibleDumper
30
29
  from ansible.utils.color import stringc
@@ -288,21 +287,21 @@ class ConfigCLI(CLI):
288
287
  default = '0'
289
288
  elif default:
290
289
  if stype == 'list':
291
- if not isinstance(default, string_types):
290
+ if not isinstance(default, str):
292
291
  # python lists are not valid env ones
293
292
  try:
294
293
  default = ', '.join(default)
295
294
  except Exception as e:
296
295
  # list of other stuff
297
296
  default = '%s' % to_native(default)
298
- if isinstance(default, string_types) and not is_quoted(default):
297
+ if isinstance(default, str) and not is_quoted(default):
299
298
  default = shlex.quote(default)
300
299
  elif default is None:
301
300
  default = ''
302
301
 
303
302
  if subkey in settings[setting] and settings[setting][subkey]:
304
303
  entry = settings[setting][subkey][-1]['name']
305
- if isinstance(settings[setting]['description'], string_types):
304
+ if isinstance(settings[setting]['description'], str):
306
305
  desc = settings[setting]['description']
307
306
  else:
308
307
  desc = '\n#'.join(settings[setting]['description'])
@@ -343,7 +342,7 @@ class ConfigCLI(CLI):
343
342
  sections[s] = new_sections[s]
344
343
  continue
345
344
 
346
- if isinstance(opt['description'], string_types):
345
+ if isinstance(opt['description'], str):
347
346
  desc = '# (%s) %s' % (opt.get('type', 'string'), opt['description'])
348
347
  else:
349
348
  desc = "# (%s) " % opt.get('type', 'string')
@@ -361,7 +360,7 @@ class ConfigCLI(CLI):
361
360
  seen[entry['section']].append(entry['key'])
362
361
 
363
362
  default = self.config.template_default(opt.get('default', ''), get_constants())
364
- if opt.get('type', '') == 'list' and not isinstance(default, string_types):
363
+ if opt.get('type', '') == 'list' and not isinstance(default, str):
365
364
  # python lists are not valid ini ones
366
365
  default = ', '.join(default)
367
366
  elif default is None: