ruamel.yaml is a YAML 1.2 loader/dumper package for Python.
| version | 0.18.17 |
| updated | 2025-12-17 |
| documentation | https://yaml.dev/doc/ruamel.yaml |
| repository | https://sourceforge.net/projects/ruamel-yaml |
| pypi | https://pypi.org/project/ruamel.yaml |
If you are interested in future upgrades of ruamel.yaml
please check the documentation on installing,
since at some point I might not be able to upload a new version to PyPI with updated information.
ruamel.yaml was intentionally named as yaml in a namespace ruamel. The namespace allows the installation
name to correspond unchanged to how the package is imported, reduces the number of links I have to create
in site-packages of a Python install during development, as well as providing a recognisable set of packages
my company releases to the public.
However, after uploading version 0.18.7, I got an email from PyPI, about having to change the project name
to ruamel_yaml to comply with PEP 625, sometime in the future. The email doesn't say if namespace packages are
no longer allowed, or how to deal with the very real clash with the pre-existing package ruamel_yaml.
I might not be able to adapt ruamel.yaml, in
a way that does not negatively affect the 0.5 million daily downloads (and my own usage of the package) in time.
My experience with other such service downgrades (Bitbucket, Readthedocs), has not been entirely positive.
This is probably the last patch version of ruamel.yaml that installs pre-compiled
ruamel.yaml.clib. This version already supports loading of the C extension
compiled using the Zig toolchain
(i.e. without you having to have a compiler environment pre-installed).
You can test this by invoking (note the final z):
python -m pip install --no-deps ruamel.yaml ruamel.yaml.clibz
You can however install both ruamel.yaml.clib and ruamel.yaml.clibz, in
which case the latter is taken (e.g. by dropping --no-deps from the invocation)
The move to using zig eliminates having to generate the 60 or so .whl files
(partly on unreliable services like AppVeyor and Github). Apart from that
the compilation on the target machine can fully optimize for that
architecture and its OS.
But the test matrix still has many dimensions:
Python versions: 3.9 - 3.14
OS-es: Linux, Alpine (musl), macOS, Windows
Architectures: Intel/AMD, Arm (and others), in 64 and some also in 32 bit versions
Zig version: ziglang < 0.16 is taken from PyPI
I try to test as much as possible, multiple Python versions were macOS-Arm and Ubuntu Linux-Intel.
And at least one Python version along each of the indicated positions of the
dimensions above (e.g. Windows10 64bit was tested, but not the RISC-V architecture).
In 0.19 the loading mechanism will be reversed: defaulting to installing and using
ruamel.yaml.clibz unless ruamel.yaml.clib is installed. This backwards
compatibility will be dropped at the end of the 0.19 series.
Pin the version that you are relying on, until you can test the changes to work for you.
As announced, in 0.18.0, the old PyYAML functions have been deprecated.
(scan, parse, compose, load, emit, serialize, dump and their variants
(_all, safe_, round_trip_, etc)). If you only read this after your program has
stopped working: I am sorry to hear that, but that also means you, or the person
developing your program, has not tested with warnings on (which is the recommendation
in PEP 565, and e.g. defaulting when using pytest). If you have troubles, explicitly use
pip install "ruamel.yaml<0.18.0"
or put something to that effects in your requirments, to give yourself
some time to solve the issue.
There will be at least one more potentially breaking change in the 0.18 series: YAML(typ='unsafe')
now has a pending deprecation warning and is going to be deprecated, probably before the end of 2023.
If you only use it to dump, please use the new YAML(typ='full'), the result of that can be safely
loaded with a default instance YAML(), as that will get you inspectable, tagged, scalars, instead of
executed Python functions/classes. (You should probably add constructors for what you actually need,
but I do consider adding a ruamel.yaml.unsafe package that will re-add the typ='unsafe' option.
Please adjust/pin your dependencies accordingly if necessary.
There seems to be a CVE on ruamel.yaml, stating that the load() function could be abused
because of unchecked input. load() was never the default function (that was round_trip_load()
before the new API came into existence. So the creator of that CVE was ill informed and
probably lazily assumed that since ruamel.yaml is a derivative of PyYAML (for which
a similar CVE exists), the same problem would still exist, without checking.
So the CVE was always inappropriate, now just more so, as the call
to the function load() with any input will terminate your program with an error message. If you
(have to) care about such things as this CVE, my recommendation is to stop using Python
completely, as pickle.load() can be abused in the same way as load() (and like unlike load()
is only documented to be unsafe, without development-time warning.
Version 0.18.9 was the last one tested to be working with Python 3.7
Version 0.17.21 was the last one tested to be working on Python 3.5 and 3.6
The 0.16.13 release was the last that was tested to be working on Python 2.7.
There are two extra plug-in packages
(ruamel.yaml.bytes and ruamel.yaml.string)
for those not wanting to do the streaming to a
io.BytesIO/StringIO buffer themselves.
If your package uses ruamel.yaml and is not listed on PyPI, drop me an
email, preferably with some information on how you use the package (or a
link to the repository) and I'll keep you informed when the status of
the API is stable enough to make the transition.
For packaging purposes you can use a download of the tar balls of tagged source
0.18.17 (2025-12-17):
_ruamel_yaml_clibz first.0.18.16 (2025-10-22):
0.18.15 (2025-08-19):
0.18.14 (2025-06-09):
0.18.13 (2025-06-06):
0.18.12 (2025-05-30):
0.18.11 (2025-05-19):
load_yaml_guess_indent now takes an option yaml argument so you can provide an already created/configured YAML instanceNotImplementedError. Reported by Karsten Tessarzik.0.18.10 (2025-01-06):
develop config)0.18.9 (2025-01-05):
0.18.8 (2025-01-02):
0.18.7 (2024-12-30):
0 (issue reported by (Mor Peled)[https://sourceforge.net/u/morp/profile/] and also in a question by Ravi on Stackoverflow)0.18.6 (2024-02-07):
InitVar fields when from __future__ import annotations was used to delay evaluation of typing.0.18.5 (2023-11-03):
0.18.4 (2023-11-01):
doc_infos attribute which is a cumulative list of DocInfo instances (one for load(), one per document for load_all()). DocInfo instances contain version information (requested, directive) and tag directive information0.18.3 (2023-10-29):
0.18.2 (2023-10-24):
AttributeError with the, somewhat more informative, orginal warning message. Instead of calling sys.exit(1)0.18.1 (2023-10-24):
0.18.0 (2023-10-23):
scan, parse, compose, load, emit, serialize, dump and their variants (_all, safe_, round_trip_, etc) have been deprecated (the same named methods on YAML() instances are, of course, still there.YAML(typ='unsafe') now issues a PendingDeprecationWarning. This will become deprecated in the 0.18 seriesYAML(typ='full') to dump unregistered Python classes/functions. bytes-like object is required not 'str' while dumping binary streams. This was reported, analysed and a fix provided by Vit Zikmund0.17.40 (2023-10-20):
!!set {a, b, c} ). Any values specified when loading are dropped, including !!null "".CommonMark.tar.gz usingRUAMEL_NO_LONG_DESCRIPTION=1 pip install ruamel.yaml --no-binary :all: then the long description, and its__repr__ for internally used classes0.17.39 (2023-10-19):
0.17.36 (2023-10-19):
Tag() instance, not a string (reported by yan12125)0.17.35 (2023-10-04):
InitVar variables (some special coding was necessary to get the, unexecpected, default value in the corresponding instance attribute ( example of usage in this question)0.17.34 (2023-10-03):
typ='safe'__post_init__() on dataclasses that have that@yaml.register_class
@dataclass
class ...
0.17.33 (2023-09-28):
flow_seq_start, flow_seq_end, flow_seq_separator, flow_map_start, flow_map_end, flow_map_separator class attributes to the Emitter class so flow style output can more easily be influenced (based on this answer on a StackOverflow question by Huw Walters).0.17.32 (2023-06-17):
0.17.31 (2023-05-31):
ScalarEvent and on Node, that takes either a Tag instance, or a str (reported by Sorin Sbarnea)0.17.30 (2023-05-30):
0.17.29 (2023-05-30):
0.17.28 (2023-05-26):
0.17.27 (2023-05-25):
CommentedMap (reported by Bastien gerard)CommentedMap key throwing error (reported by John Thorvald Wodder II)0.17.26 (2023-05-09):
0.17.25 (2023-05-09):
0.17.24 (2023-05-06):
CommentedMap.insert(). If you have a merge key in the YAML document for the mapping you insert to, the position value should be the one as you look at the YAML input. This fixes issue 453 where other keys of a merged in mapping would show up after an insert (reported by Alex Miller). It also fixes a call to .insert() resulting into the merge key to move to be the first key if it wasn't already and it is also now possible to insert a key before a merge key (even if the fist key in the mapping).0.17.23 (2023-05-05):
.update() no longer correctly handling keyword arguments (reported by John Lin on StackOverflow)0.17.22 (2023-05-02):
__repr__ of CommentedMap, now that Python's dict is ordered -> no more ordereddict(list-of-tuples)!!float 42 (reported by Eric on Stack overflow)CommentedKeySeq and CommentedKeyMap (which are created if you have a sequence resp. mapping as the key in a mapping)0.17.21 (2022-02-12):
.compose() method with pathlib.Path instance.0.17.20 (2022-01-03):
0.17.19 (2021-12-26):
0.17.18 (2021-12-24):
0.17.17 (2021-10-31):
0.17.16 (2021-08-28):
0.17.15 (2021-08-28):
0.17.14 (2021-08-25):
0.17.13 (2021-08-21):
0.17.12 (2021-08-21):
@attr.s() (both reported by ssph)0.17.11 (2021-08-19):
DuplicateKeyError (reported by Łukasz Rogalski)KeyError during reader error (reported by MTU)0.17.10 (2021-06-24):
0.17.9 (2021-06-10):
0.17.8 (2021-06-09):
0.17.7 (2021-05-31):
0.17.6 (2021-05-31):
0.17.5 (2021-05-30):
!!set with aliased entry resulting in broken YAML on rt reported by William Kimball)0.17.4 (2021-04-07):
0.17.3 (2021-04-07):
yaml.composer.return_alias = lambda s: copy.deepcopy(s)0.17.2 (2021-03-29):
0.17.1 (2021-03-29):
0.17.0 (2021-03-26):
ruamel.std.pathlib)_Fload, safe_load, round_trip_load, dump, safe_dump, round_trip_dump, scan, parse, compose, emit, serialize as well as their _all variants for multi-document streams, now issue a PendingDeprecationning (e.g. when run from pytest, but also Python is started with -Wd). Use the methods on YAML(), which have been extended.# column of a following comment.For older changes see the file
CHANGES