{"id":10207,"library":"saneyaml","title":"SaneYAML","description":"SaneYAML (version 0.6.1) is a lightweight wrapper around PyYAML designed to provide a safer and more predictable experience when reading and writing configuration files. It focuses on preserving dictionary order and preventing common PyYAML footguns such as unwanted implicit type conversions for strings like 'yes', 'no', dates, or numbers. Its release cadence is sporadic, focusing on stability and essential bug fixes.","status":"active","version":"0.6.1","language":"en","source_language":"en","source_url":"https://github.com/aboutcode-org/saneyaml","tags":["YAML","configuration","PyYAML","safe","order-preserving","parser","serializer"],"install":[{"cmd":"pip install saneyaml","lang":"bash","label":"Install SaneYAML"}],"dependencies":[{"reason":"SaneYAML is a wrapper around PyYAML and requires it to function. It uses specific PyYAML loaders and dumpers for its 'sane' behavior.","package":"PyYAML","optional":false}],"imports":[{"symbol":"load","correct":"from saneyaml import load"},{"symbol":"dump","correct":"from saneyaml import dump"}],"quickstart":{"code":"from saneyaml import load, dump\nimport io\n\n# Example YAML data\nconfig_data = {\n    'name': 'My App',\n    'version': '1.0.0',\n    'settings': {\n        'debug': 'No',  # saneyaml keeps this as string, not bool\n        'log_level': 'INFO',\n        'features': ['alpha', 'beta']\n    },\n    'last_updated': '2023-10-27' # saneyaml keeps this as string, not datetime\n}\n\n# Dump to a YAML string (preserving order and types)\noutput_stream = io.StringIO()\ndump(config_data, output_stream)\nyaml_string = output_stream.getvalue()\nprint(\"\\n--- Dumped YAML ---\\n\" + yaml_string)\n\n# Load from a YAML string (preventing implicit conversions)\nloaded_data = load(yaml_string)\n\nprint(\"\\n--- Loaded Data ---\")\nprint(f\"Debug setting type: {type(loaded_data['settings']['debug'])} (value: {loaded_data['settings']['debug']})\")\nprint(f\"Last updated type: {type(loaded_data['last_updated'])} (value: {loaded_data['last_updated']})\")\nprint(f\"Loaded data equality: {loaded_data == config_data}\")\n\n# Demonstrate order preservation (requires Python 3.7+ for dicts)\n# For older Pythons, saneyaml handles order internally.\noriginal_keys = list(config_data.keys())\nloaded_keys = list(loaded_data.keys())\nprint(f\"Original top-level keys order: {original_keys}\")\nprint(f\"Loaded top-level keys order: {loaded_keys}\")","lang":"python","description":"This quickstart demonstrates how to use `saneyaml.load` and `saneyaml.dump` to process YAML data. It highlights SaneYAML's core features: preserving order of keys and preventing implicit type conversions for values like 'yes', 'no', or date strings, which are often problematic in default PyYAML usage. Notice how 'No' and '2023-10-27' are loaded as strings, not booleans or datetime objects."},"warnings":[{"fix":"Explicitly convert loaded string values to the desired type in your application logic (e.g., `value == 'yes'` or `datetime.fromisoformat(value)`). This is the intended behavior of `saneyaml` to avoid surprises.","message":"SaneYAML deliberately disables implicit type conversions for common string values like 'yes', 'no', 'on', 'off', dates, and some numbers. This means `yes` will be loaded as the string 'yes', not the boolean `True`. If you expect PyYAML's default 'smart' parsing, your code might receive `str` instead of `bool` or `datetime` objects.","severity":"gotcha","affected_versions":"All versions"},{"fix":"For complex YAML features or highly customized serialization, consider using `ruamel.yaml` or interacting directly with `PyYAML`'s `SafeLoader` and `SafeDumper` with custom configurations. `saneyaml` is best suited for straightforward configuration files.","message":"While `saneyaml` preserves insertion order for mappings (dictionaries), if your application relies on PyYAML's advanced features like custom constructors/representers, anchors, or tags, `saneyaml` might not expose them directly or might override their behavior for safety. It prioritizes a simpler, more controlled YAML experience.","severity":"gotcha","affected_versions":"All versions"},{"fix":"Ensure your environment uses Python 3.7 or newer for consistent dictionary order behavior. `saneyaml` itself has mechanisms to preserve order, but downstream processing with older Python dicts could lose it.","message":"Prior to Python 3.7, standard `dict` objects did not guarantee insertion order. `saneyaml` handles this internally to preserve order during dump/load. However, if mixing `saneyaml` with older Python versions and other YAML libraries, unexpected order behavior might occur due to underlying dictionary implementations.","severity":"breaking","affected_versions":"< 0.5.0 (and Python < 3.7)"}],"env_vars":null,"last_verified":"2026-04-17T00:00:00.000Z","next_check":"2026-07-16T00:00:00.000Z","problems":[{"fix":"Review the YAML file or string for syntax errors. YAML is highly sensitive to indentation. Use an online YAML validator or a linter in your IDE to pinpoint issues.","cause":"This error, or a generic `YAMLError`, indicates malformed YAML input. Common causes include incorrect indentation, missing colons, or invalid syntax.","error":"saneyaml.parser.ParserError: while parsing a block mapping"},{"fix":"Install `libyaml` development headers on your operating system (e.g., `sudo apt-get install libyaml-dev` on Debian/Ubuntu, `brew install libyaml` on macOS, or `choco install libyaml` on Windows). Then, reinstall `PyYAML` using `pip install --force-reinstall PyYAML` to ensure it compiles with the C extensions.","cause":"This issue originates from the underlying `PyYAML` library and means it failed to load its C-based extensions, typically because the `libyaml` development headers are missing on your system.","error":"AttributeError: 'module' object has no attribute 'CLoader'"},{"fix":"Compare the string value explicitly (e.g., `if loaded_data['key'] == 'yes':`). For other types like dates, use appropriate parsing functions (e.g., `datetime.fromisoformat(loaded_data['date_key'])`).","cause":"You are attempting to convert a string loaded by `saneyaml` (e.g., 'yes', 'no') directly to a boolean or another type, but `saneyaml` intentionally loads these as strings to prevent implicit conversions.","error":"ValueError: invalid literal for bool(): 'yes'"}]}