mirror of
https://github.com/ansible/ansible.git
synced 2026-02-03 20:40:24 -05:00
Fix YAML string loading using Python loader
This commit is contained in:
parent
330f40b4f5
commit
52ed1759fb
4 changed files with 34 additions and 4 deletions
2
changelogs/fragments/pyyaml-name.yml
Normal file
2
changelogs/fragments/pyyaml-name.yml
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
bugfixes:
|
||||
- yaml loading - Fix traceback when parsing YAML strings (not files) when using the pure Python implementation of PyYAML.
|
||||
|
|
@ -13,22 +13,20 @@ from ._constructor import AnsibleConstructor, AnsibleInstrumentedConstructor
|
|||
if HAS_LIBYAML:
|
||||
from yaml.cyaml import CParser
|
||||
|
||||
class _YamlParser(CParser):
|
||||
class _Parser(CParser):
|
||||
def __init__(self, stream: str | bytes | _io.IOBase) -> None:
|
||||
if isinstance(stream, (str, bytes)):
|
||||
stream = AnsibleTagHelper.untag(stream) # PyYAML + libyaml barfs on str/bytes subclasses
|
||||
|
||||
CParser.__init__(self, stream)
|
||||
|
||||
self.name = getattr(stream, 'name', None) # provide feature parity with the Python implementation (yaml.reader.Reader provides name)
|
||||
|
||||
else:
|
||||
from yaml.composer import Composer
|
||||
from yaml.reader import Reader
|
||||
from yaml.scanner import Scanner
|
||||
from yaml.parser import Parser
|
||||
|
||||
class _YamlParser(Reader, Scanner, Parser, Composer): # type: ignore[no-redef]
|
||||
class _Parser(Reader, Scanner, Parser, Composer): # type: ignore[no-redef]
|
||||
def __init__(self, stream: str | bytes | _io.IOBase) -> None:
|
||||
Reader.__init__(self, stream)
|
||||
Scanner.__init__(self)
|
||||
|
|
@ -36,6 +34,17 @@ else:
|
|||
Composer.__init__(self)
|
||||
|
||||
|
||||
class _YamlParser(_Parser):
|
||||
def __init__(self, stream: str | bytes | _io.IOBase) -> None:
|
||||
super().__init__(stream)
|
||||
|
||||
# The Python implementation of PyYAML (yaml.reader.Reader) provides self.name.
|
||||
# However, it will fall back to "<...>" in various cases.
|
||||
# The C implementation of PyYAML does not provide self.name.
|
||||
# To provide consistency, name retrieval is re-implemented here.
|
||||
self.name = getattr(stream, 'name', None)
|
||||
|
||||
|
||||
class AnsibleInstrumentedLoader(_YamlParser, AnsibleInstrumentedConstructor, Resolver):
|
||||
"""Ansible YAML loader which supports Ansible custom behavior such as `Origin` tagging, but no Ansible-specific YAML tags."""
|
||||
|
||||
|
|
|
|||
|
|
@ -4,8 +4,18 @@ set -eu -o pipefail
|
|||
source virtualenv.sh
|
||||
set +x
|
||||
|
||||
# Verify libyaml is in use.
|
||||
ansible --version | tee /dev/stderr | grep 'with libyaml'
|
||||
|
||||
# Run tests with libyaml.
|
||||
ansible-playbook runme.yml "${@}"
|
||||
|
||||
# deps are already installed, using --no-deps to avoid re-installing them
|
||||
# Install PyYAML without libyaml to validate ansible can run
|
||||
PYYAML_FORCE_LIBYAML=0 pip install --no-binary PyYAML --ignore-installed --no-cache-dir --no-deps PyYAML
|
||||
|
||||
# Verify libyaml is not in use.
|
||||
ansible --version | tee /dev/stderr | grep 'without libyaml'
|
||||
|
||||
# Run tests without libyaml.
|
||||
ansible-playbook runme.yml "${@}"
|
||||
|
|
|
|||
9
test/integration/targets/pyyaml/runme.yml
Normal file
9
test/integration/targets/pyyaml/runme.yml
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
- hosts: localhost
|
||||
gather_facts: no
|
||||
tasks:
|
||||
- name: Read YAML from a string
|
||||
assert:
|
||||
that:
|
||||
- "'1' | from_yaml == 1"
|
||||
- "'[1]' | from_yaml == [1]"
|
||||
- "'key: value' | from_yaml == {'key': 'value'}"
|
||||
Loading…
Reference in a new issue