{"id":7926,"library":"antsibull-fileutils","title":"antsibull-fileutils","description":"antsibull-fileutils is a Python library providing file utility functions primarily used by other community Ansible tools. It's an integral part of the broader antsibull ecosystem, which assists in building the Ansible Distribution. The library follows semantic versioning from version 1.0.0 onwards, aiming to avoid backward-incompatible changes within a major release cycle, though exceptions may occur for critical security fixes.","status":"active","version":"1.5.2","language":"en","source_language":"en","source_url":"https://github.com/ansible-community/antsibull-fileutils","tags":["ansible","file-utilities","ansible-collections","development-tools","filesystem"],"install":[{"cmd":"pip install antsibull-fileutils","lang":"bash","label":"Install latest version"}],"dependencies":[{"reason":"Used for YAML parsing and manipulation.","package":"pyyaml","optional":false},{"reason":"Likely used for asynchronous file operations.","package":"aiofiles","optional":false}],"imports":[{"note":"A utility for writing content to a file.","symbol":"write_file","correct":"from antsibull_fileutils.io import write_file"},{"note":"Creates a temporary directory in a manner consistent with Ansible's needs.","symbol":"ansible_mkdtemp","correct":"from antsibull_fileutils.tempfile import ansible_mkdtemp"},{"note":"A class for copying Ansible collections.","symbol":"CollectionCopier","correct":"from antsibull_fileutils.copier import CollectionCopier"}],"quickstart":{"code":"from antsibull_fileutils.io import write_file\nfrom antsibull_fileutils.tempfile import ansible_mkdtemp, AnsibleTemporaryDirectory\nimport os\n\n# Example 1: Writing to a file\ntry:\n    temp_dir = ansible_mkdtemp()\n    file_path = os.path.join(temp_dir, \"test_file.txt\")\n    content = \"Hello, antsibull-fileutils!\"\n    write_file(file_path, content.encode('utf-8'))\n    with open(file_path, 'r') as f:\n        read_content = f.read()\n    print(f\"Successfully wrote and read: {read_content}\")\nexcept Exception as e:\n    print(f\"Error: {e}\")\nfinally:\n    # In a real application, you'd clean up the temp_dir\n    print(f\"Temporary directory created at: {temp_dir}\")\n\n# Example 2: Using AnsibleTemporaryDirectory context manager\nwith AnsibleTemporaryDirectory() as temp_dir_obj:\n    print(f\"Temporary directory (context manager): {temp_dir_obj.name}\")\n    another_file_path = os.path.join(temp_dir_obj.name, \"another_file.txt\")\n    write_file(another_file_path, b\"Context manager test\")\n    assert os.path.exists(another_file_path)\nprint(\"Temporary directory from context manager cleaned up automatically.\")","lang":"python","description":"This quickstart demonstrates how to use `write_file` to write content to a file and `ansible_mkdtemp` or `AnsibleTemporaryDirectory` to create and manage temporary directories, which are common file operations provided by the library. Note that `write_file` expects bytes for content."},"warnings":[{"fix":"Review existing code that relies on specific symlink handling when copying files or directories to ensure the new behavior aligns with expectations. Adjust logic if necessary, especially for external symlinks.","message":"The handling of symlinks by `Copier` and `GitCopier` classes was rewritten in version 1.5.0. Previously, symlinks outside the copied tree might have been linked, but now their content is copied. Symlinks inside the tree are preserved, and symlinks are normalized by default.","severity":"gotcha","affected_versions":">=1.5.0"},{"fix":"Consider updating code that interacts with `CollectionCopier.source_directory` to use `pathlib.Path` for better interoperability with modern Python path handling, especially if new `pathlib` features are desired.","message":"As of version 1.0.1, the `CollectionCopier`'s `source_directory` argument explicitly supports `pathlib.Path` objects in addition to `str`. While existing code using `str` will continue to function, leveraging `pathlib.Path` can provide more robust path manipulation.","severity":"gotcha","affected_versions":">=1.0.1"},{"fix":"Always check the `install_requires` or release notes of other `antsibull-*` libraries you are using to confirm compatible versions of `antsibull-fileutils` before updating.","message":"`antsibull-fileutils` is a core dependency for several other `antsibull-*` projects (e.g., `antsibull-nox`, `antsibull-changelog`, `antsibull-docs`). When upgrading or installing, ensure compatibility between `antsibull-fileutils` and its dependent libraries to avoid unexpected issues or runtime errors. For instance, `antsibull-nox` >= 1.5.0 requires `antsibull-fileutils` >= 1.5.0.","severity":"gotcha","affected_versions":"All versions"}],"env_vars":null,"last_verified":"2026-04-16T00:00:00.000Z","next_check":"2026-07-15T00:00:00.000Z","problems":[{"fix":"Ensure the target directory exists before writing, or that the source file exists before reading/copying. Verify the Python process has the necessary read/write/execute permissions for the relevant paths. Use `os.makedirs(os.path.dirname(file_path), exist_ok=True)` to create parent directories if needed.","cause":"Attempting to perform file operations (read, write, copy) on a non-existent path or without sufficient file system permissions for the current user.","error":"FileNotFoundError: [Errno 2] No such file or directory: '...' or PermissionError: [Errno 13] Permission denied: '...'"},{"fix":"If your workflow depends on preserving external symlinks as actual links, you may need to implement custom logic to identify and handle these links separately, or adjust your process to expect the content to be copied. Always test your file copying operations after upgrading `antsibull-fileutils` to v1.5.0 or later if symlinks are involved.","cause":"Prior to `antsibull-fileutils` v1.5.0, symlinks outside the tree might have been preserved as links. Since v1.5.0, `Copier` and `GitCopier` will copy the *content* of external symlinks instead of preserving the link itself, if they point outside the copied tree.","error":"Unexpected content copied when dealing with symlinks."}]}