mudio 1.0.0__tar.gz

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.
mudio-1.0.0/.gitignore ADDED
@@ -0,0 +1,130 @@
1
+ # Byte-compiled / optimized / DLL files
2
+ __pycache__/
3
+ *.py[cod]
4
+ *$py.class
5
+
6
+ # C extensions
7
+ *.so
8
+
9
+ # Distribution / packaging
10
+ .Python
11
+ build/
12
+ develop-eggs/
13
+ dist/
14
+ downloads/
15
+ eggs/
16
+ .eggs/
17
+ lib/
18
+ lib64/
19
+ parts/
20
+ sdist/
21
+ var/
22
+ wheels/
23
+ share/python-wheels/
24
+ *.egg-info/
25
+ .installed.cfg
26
+ *.egg
27
+ MANIFEST
28
+
29
+ # PyInstaller
30
+ *.manifest
31
+ *.spec
32
+
33
+ # Installer logs
34
+ pip-log.txt
35
+ pip-delete-this-directory.txt
36
+
37
+ # Unit test / coverage reports
38
+ htmlcov/
39
+ .tox/
40
+ .nox/
41
+ .coverage
42
+ .coverage.*
43
+ .cache
44
+ nosetests.xml
45
+ coverage.xml
46
+ *.cover
47
+ *.py,cover
48
+ .hypothesis/
49
+ .pytest_cache/
50
+
51
+ # Translations
52
+ *.mo
53
+ *.pot
54
+
55
+ # Django stuff:
56
+ *.log
57
+ local_settings.py
58
+ db.sqlite3
59
+ db.sqlite3-journal
60
+
61
+ # Flask stuff:
62
+ instance/
63
+ .webassets-cache
64
+
65
+ # Scrapy stuff:
66
+ .scrapy
67
+
68
+ # Sphinx documentation
69
+ docs/_build/
70
+
71
+ # PyBuilder
72
+ target/
73
+
74
+ # Jupyter Notebook
75
+ .ipynb_checkpoints
76
+
77
+ # IPython
78
+ profile_default/
79
+ ipython_config.py
80
+
81
+ # pyenv
82
+ .python-version
83
+
84
+ # pipenv
85
+ Pipfile.lock
86
+
87
+ # PEP 582
88
+ __pypackages__/
89
+
90
+ # Celery stuff
91
+ celerybeat-schedule
92
+ celerybeat.pid
93
+
94
+ # SageMath parsed files
95
+ *.sage.py
96
+
97
+ # Environments
98
+ .env
99
+ .venv
100
+ env/
101
+ venv/
102
+ ENV/
103
+ env.bak/
104
+ venv.bak/
105
+
106
+ # Spyder project settings
107
+ .spyderproject
108
+ .spyproject
109
+
110
+ # Rope project settings
111
+ .ropeproject
112
+
113
+ # mkdocs documentation
114
+ /site
115
+
116
+ # mypy
117
+ .mypy_cache/
118
+ .dmypy.json
119
+ dmypy.json
120
+
121
+ # Pyre type checker
122
+ .pyre/
123
+
124
+ # Project-specific
125
+ logs/
126
+ *.log
127
+ test_artifacts/
128
+
129
+ venv/
130
+ benchmark_results.png
mudio-1.0.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Matthew Deik
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
mudio-1.0.0/PKG-INFO ADDED
@@ -0,0 +1,153 @@
1
+ Metadata-Version: 2.4
2
+ Name: mudio
3
+ Version: 1.0.0
4
+ Summary: Friendly command-line music-metadata editor and Python library
5
+ Project-URL: Homepage, https://github.com/mdeik/mudio
6
+ Project-URL: Repository, https://github.com/mdeik/mudio
7
+ Author-email: Matthew Deik <131482791+mdeik@users.noreply.github.com>
8
+ License: MIT
9
+ License-File: LICENSE
10
+ Requires-Python: >=3.8
11
+ Requires-Dist: mutagen>=1.47.0
12
+ Provides-Extra: dev
13
+ Requires-Dist: pytest-cov; extra == 'dev'
14
+ Requires-Dist: pytest>=7.0; extra == 'dev'
15
+ Description-Content-Type: text/markdown
16
+
17
+ # mudio
18
+
19
+ **mudio** is a powerful, friendly command-line music metadata editor and Python library. It provides a unified API for handling metadata across MP3, FLAC, M4A, and more, making batch processing and automation simple and safe.
20
+
21
+ ## Features
22
+
23
+ - **Unified API**: Write code once, run it on MP3, FLAC, M4A, WAV, OGG, OPUS, WMA, and WavPack.
24
+ - **Batch Processing**: robust CLI for processing thousands of files.
25
+ - **Parallel Execution**: Automatically uses multi-threading for large batches.
26
+ - **Safety First**: Built-in **backup** system, **dry-run** mode, and careful validation.
27
+ - **Powerful Operations**:
28
+ - **Find & Replace**: Regex-supported search and replace in tags.
29
+ - **Mass Edits**: Set, overwrite, append, prefix, or clear tags.
30
+ - **Filtering**: Apply changes only to files matching specific criteria (e.g. `artist="The Beatles"`).
31
+
32
+ ## Supported Formats
33
+
34
+ - **MP3** (`.mp3`) - ID3v2.3/v2.4
35
+ - **FLAC** (`.flac`) - Vorbis Comments
36
+ - **M4A / MP4** (`.m4a`, `.mp4`) - MP4 Tags
37
+ - **Ogg Vorbis** (`.ogg`)
38
+ - **Opus** (`.opus`)
39
+ - **WAV** (`.wav`)
40
+ - **Windows Media Audio** (`.wma`)
41
+ - **WavPack** (`.wv`)
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ pip install mudio
47
+ ```
48
+
49
+ ## CLI Usage
50
+
51
+ `mudio` is designed for efficient batch operations.
52
+
53
+ ### Basic Commands
54
+
55
+ ```bash
56
+ # View metadata
57
+ mudio song.mp3 --mode view
58
+
59
+ # Set Album and Date
60
+ mudio *.mp3 --mode set --album "New Album" --date "2024"
61
+
62
+ # View metadata (truncated if long)
63
+ mudio song.mp3 --mode print
64
+
65
+ # Overwrite Title
66
+ mudio song.flac --mode overwrite --fields title --value "My Song"
67
+ ```
68
+
69
+ ### Advanced Batch Operations
70
+
71
+ ```bash
72
+ # Regex Find & Replace (Fix features)
73
+ # Changes "feat." -> "ft." in title and artist
74
+ mudio /music --recursive \
75
+ --mode find-replace --find "feat\." --replace "ft." --regex \
76
+ --fields title,artist
77
+
78
+ For full command details, see the [CLI Reference](docs/cli_reference.md).
79
+ For code API details, see the [API Reference](docs/api_reference.md).
80
+
81
+ # Append to Comment
82
+ mudio *.m4a --mode append --fields comment --value " [Remastered]"
83
+
84
+ # Filtered Processing
85
+ # Only add "Rock" genre to tracks by "Led Zeppelin"
86
+ mudio /library --recursive \
87
+ --filter "artist=Led Zeppelin" \
88
+ --mode overwrite --fields genre --value "Rock"
89
+ ```
90
+
91
+ ### Safety Features
92
+
93
+ ```bash
94
+ # Dry Run (See what would happen without modifying files)
95
+ mudio *.mp3 --mode set --album "Test" --dry-run
96
+
97
+ # Create Backups (Saved to ./backups/)
98
+ mudio *.flac --mode clear --fields comment --backup ./backups
99
+ ```
100
+
101
+ ## Python Library Usage
102
+
103
+ `mudio` provides a Pythonic wrapper around `mutagen` for scripts and tools.
104
+
105
+ ```python
106
+ from mudio import SimpleMusic
107
+
108
+ # Reading
109
+ with SimpleMusic("song.flac") as sm:
110
+ print(sm.read_fields())
111
+ # {'artist': ['The Band'], 'title': ['The Song'], ...}
112
+
113
+ # Writing
114
+ with SimpleMusic("song.mp3") as sm:
115
+ sm.write_fields({
116
+ 'title': ['New Title'],
117
+ 'genre': ['Pop', 'Rock'] # Multi-value support
118
+ })
119
+
120
+ # Error handling is managed by the context manager
121
+ ```
122
+
123
+ ## Comparison with Alternatives
124
+
125
+ ### vs. **Mutagen**
126
+ - **Mutagen** is the low-level library that `mudio` uses. It is powerful but requires learning different APIs for ID3, Vorbis, and MP4 tags.
127
+ - **mudio** abstracts these differences. Use `mudio` if you want a simple, unified API (e.g. `sm.write_fields({'title': ...})` works on everything). Use `mutagen` if you need byte-level control or support for obscure frame types.
128
+
129
+ ### vs. **Beets**
130
+ - **Beets** is a complete library manager with a centralized database, autotagger, and plugin system. It implies a workflow where it "owns" your library.
131
+ - **mudio** is a stateless tool. It modifies files directly without a database. Use `mudio` for quick fixes, batch scripting, or if you prefer managing your file structure manually.
132
+
133
+ ### vs. **Picard**
134
+ - **MusicBrainz Picard** is a GUI application focused on matching files to the MusicBrainz database.
135
+ - **mudio** is a CLI/Library tool. It's better for automation, headless servers, or mass-editing tags based on patterns rather than database matching.
136
+
137
+ ### vs. **music_tag**
138
+ - **music_tag** is a library primarily for Python scripts, offering a dictionary-like interface. It is excellent for simple script usage.
139
+ - **mudio** offers similar library features but includes a **robust CLI** for batch processing, filtering, and safety operations (backups, dry-runs) out of the box.
140
+
141
+ ### vs. **EyeD3**
142
+ - **EyeD3** is excellent but specific to MP3/ID3.
143
+ - **mudio** supports FLAC, M4A, OGG, and more with the same commands.
144
+
145
+ ## Development
146
+
147
+ ```bash
148
+ # Install dependencies
149
+ pip install -e ".[dev]"
150
+
151
+ # Run tests
152
+ pytest
153
+ ```
mudio-1.0.0/README.md ADDED
@@ -0,0 +1,137 @@
1
+ # mudio
2
+
3
+ **mudio** is a powerful, friendly command-line music metadata editor and Python library. It provides a unified API for handling metadata across MP3, FLAC, M4A, and more, making batch processing and automation simple and safe.
4
+
5
+ ## Features
6
+
7
+ - **Unified API**: Write code once, run it on MP3, FLAC, M4A, WAV, OGG, OPUS, WMA, and WavPack.
8
+ - **Batch Processing**: robust CLI for processing thousands of files.
9
+ - **Parallel Execution**: Automatically uses multi-threading for large batches.
10
+ - **Safety First**: Built-in **backup** system, **dry-run** mode, and careful validation.
11
+ - **Powerful Operations**:
12
+ - **Find & Replace**: Regex-supported search and replace in tags.
13
+ - **Mass Edits**: Set, overwrite, append, prefix, or clear tags.
14
+ - **Filtering**: Apply changes only to files matching specific criteria (e.g. `artist="The Beatles"`).
15
+
16
+ ## Supported Formats
17
+
18
+ - **MP3** (`.mp3`) - ID3v2.3/v2.4
19
+ - **FLAC** (`.flac`) - Vorbis Comments
20
+ - **M4A / MP4** (`.m4a`, `.mp4`) - MP4 Tags
21
+ - **Ogg Vorbis** (`.ogg`)
22
+ - **Opus** (`.opus`)
23
+ - **WAV** (`.wav`)
24
+ - **Windows Media Audio** (`.wma`)
25
+ - **WavPack** (`.wv`)
26
+
27
+ ## Installation
28
+
29
+ ```bash
30
+ pip install mudio
31
+ ```
32
+
33
+ ## CLI Usage
34
+
35
+ `mudio` is designed for efficient batch operations.
36
+
37
+ ### Basic Commands
38
+
39
+ ```bash
40
+ # View metadata
41
+ mudio song.mp3 --mode view
42
+
43
+ # Set Album and Date
44
+ mudio *.mp3 --mode set --album "New Album" --date "2024"
45
+
46
+ # View metadata (truncated if long)
47
+ mudio song.mp3 --mode print
48
+
49
+ # Overwrite Title
50
+ mudio song.flac --mode overwrite --fields title --value "My Song"
51
+ ```
52
+
53
+ ### Advanced Batch Operations
54
+
55
+ ```bash
56
+ # Regex Find & Replace (Fix features)
57
+ # Changes "feat." -> "ft." in title and artist
58
+ mudio /music --recursive \
59
+ --mode find-replace --find "feat\." --replace "ft." --regex \
60
+ --fields title,artist
61
+
62
+ For full command details, see the [CLI Reference](docs/cli_reference.md).
63
+ For code API details, see the [API Reference](docs/api_reference.md).
64
+
65
+ # Append to Comment
66
+ mudio *.m4a --mode append --fields comment --value " [Remastered]"
67
+
68
+ # Filtered Processing
69
+ # Only add "Rock" genre to tracks by "Led Zeppelin"
70
+ mudio /library --recursive \
71
+ --filter "artist=Led Zeppelin" \
72
+ --mode overwrite --fields genre --value "Rock"
73
+ ```
74
+
75
+ ### Safety Features
76
+
77
+ ```bash
78
+ # Dry Run (See what would happen without modifying files)
79
+ mudio *.mp3 --mode set --album "Test" --dry-run
80
+
81
+ # Create Backups (Saved to ./backups/)
82
+ mudio *.flac --mode clear --fields comment --backup ./backups
83
+ ```
84
+
85
+ ## Python Library Usage
86
+
87
+ `mudio` provides a Pythonic wrapper around `mutagen` for scripts and tools.
88
+
89
+ ```python
90
+ from mudio import SimpleMusic
91
+
92
+ # Reading
93
+ with SimpleMusic("song.flac") as sm:
94
+ print(sm.read_fields())
95
+ # {'artist': ['The Band'], 'title': ['The Song'], ...}
96
+
97
+ # Writing
98
+ with SimpleMusic("song.mp3") as sm:
99
+ sm.write_fields({
100
+ 'title': ['New Title'],
101
+ 'genre': ['Pop', 'Rock'] # Multi-value support
102
+ })
103
+
104
+ # Error handling is managed by the context manager
105
+ ```
106
+
107
+ ## Comparison with Alternatives
108
+
109
+ ### vs. **Mutagen**
110
+ - **Mutagen** is the low-level library that `mudio` uses. It is powerful but requires learning different APIs for ID3, Vorbis, and MP4 tags.
111
+ - **mudio** abstracts these differences. Use `mudio` if you want a simple, unified API (e.g. `sm.write_fields({'title': ...})` works on everything). Use `mutagen` if you need byte-level control or support for obscure frame types.
112
+
113
+ ### vs. **Beets**
114
+ - **Beets** is a complete library manager with a centralized database, autotagger, and plugin system. It implies a workflow where it "owns" your library.
115
+ - **mudio** is a stateless tool. It modifies files directly without a database. Use `mudio` for quick fixes, batch scripting, or if you prefer managing your file structure manually.
116
+
117
+ ### vs. **Picard**
118
+ - **MusicBrainz Picard** is a GUI application focused on matching files to the MusicBrainz database.
119
+ - **mudio** is a CLI/Library tool. It's better for automation, headless servers, or mass-editing tags based on patterns rather than database matching.
120
+
121
+ ### vs. **music_tag**
122
+ - **music_tag** is a library primarily for Python scripts, offering a dictionary-like interface. It is excellent for simple script usage.
123
+ - **mudio** offers similar library features but includes a **robust CLI** for batch processing, filtering, and safety operations (backups, dry-runs) out of the box.
124
+
125
+ ### vs. **EyeD3**
126
+ - **EyeD3** is excellent but specific to MP3/ID3.
127
+ - **mudio** supports FLAC, M4A, OGG, and more with the same commands.
128
+
129
+ ## Development
130
+
131
+ ```bash
132
+ # Install dependencies
133
+ pip install -e ".[dev]"
134
+
135
+ # Run tests
136
+ pytest
137
+ ```
@@ -0,0 +1,175 @@
1
+ # mudio API Reference
2
+
3
+ This document provides a detailed reference for the internal Python API of `mudio`. It is useful for developers who want to use `mudio` as a library in their own scripts or applications.
4
+
5
+ ## Core (`mudio.core`)
6
+
7
+ The core module handles the abstraction layer for reading and writing metadata across different audio formats.
8
+
9
+ ### `SimpleMusic`
10
+
11
+ The primary interface for interacting with audio files. It automatically handles format detection (MP3, FLAC, M4A, etc.) and provides a unified dictionary-based API for tags.
12
+
13
+ ```python
14
+ from mudio.core import SimpleMusic, managed_simple_music
15
+
16
+ # Recommended: Use context manager to ensure files are closed safely
17
+ with managed_simple_music("path/to/song.mp3") as sm:
18
+ fields = sm.read_fields()
19
+ sm.write_fields({"title": ["New Title"]})
20
+ ```
21
+
22
+ #### Class Reference
23
+
24
+ **`SimpleMusic(path: Union[str, Path])`**
25
+ * **path**: The file path to open.
26
+ * **Raises**:
27
+ * `FormatError`: If the file format is unsupported or corrupted.
28
+ * `RuntimeError`: If the file does not exist.
29
+
30
+ **`SimpleMusic.read_fields(mode: str = 'canonical') -> Dict[str, List[str]]`**
31
+ Reads metadata fields from the file.
32
+ * **mode**:
33
+ * `'canonical'` (default): Returns a standardized dictionary using `mudio`'s canonical field names (e.g. `title`, `artist`, `date`).
34
+ * `'raw'`: Returns the raw mapping of tags as they appear in the file (e.g. `TIT2` for MP3 title, `©nam` for MP4).
35
+ * `'extended'`: Returns all canonical fields **plus** any other fields found in the file that didn't map to a canonical one (e.g. `acoustid_id`, custom TXXX frames).
36
+ * **Returns**: A dictionary where keys are field names and values are a **list of strings**.
37
+ * **Note**: `mudio` uses a unified list-based structure for I/O consistency. However, fields have semantic cardinality:
38
+ * **Single-valued** (e.g. `title`, `date`, `track`): Logic operations will typically use only the first value.
39
+ * **Multi-valued** (e.g. `artist`, `genre`): Logic operations maintain the full list.
40
+ * See `mudio.operations` for field definitions.
41
+
42
+ **`SimpleMusic.write_fields(fields: Dict[str, List[str]])`**
43
+ Writes metadata to the file.
44
+ * **Raises**:
45
+ * `PermissionError`: If the file is not writable.
46
+ * `RuntimeError`: If no file is loaded.
47
+ * **fields**: A dictionary of fields to write. Keys can be canonical field names (like `title`, `artist`) or **any custom string**.
48
+ * **Behavior**:
49
+ * **Custom Fields**: Arbitrary keys are written as format-specific custom tags (TXXX for ID3, comments for Vorbis, freeform atoms for MP4).
50
+ * Existing fields not in the input dictionary are **preserved**. (To delete a field, use `delete_fields` or pass an empty list `[]` as the value).
51
+ * This method transparently handles format-specific details.
52
+
53
+ **`SimpleMusic.delete_fields(fields: List[str])`**
54
+ Deletes the specified fields from the file.
55
+ * **fields**: List of canonical or custom field names to remove.
56
+
57
+ **`SimpleMusic.close()`**
58
+ Closes the underlying file handle. Automatically called when using the context manager.
59
+
60
+ **`SimpleMusic.parse_list_string(s: Optional[str], delimiter: str = ';') -> List[str]`**
61
+ Static utility method to split a string into a list based on a delimiter.
62
+ * **s**: The string to parse.
63
+ * **delimiter**: The delimiter character (default `;`).
64
+ * **Returns**: List of strings, stripped of whitespace.
65
+
66
+ ---
67
+
68
+ ## Processor (`mudio.processor`)
69
+
70
+ The processor module handles high-level batch processing, including parallel execution, file validation, backups, and error reporting.
71
+
72
+ ### Batch Processing Functions
73
+
74
+ **`process_files(files: Iterable[Path], ops: FieldOperationsType, targeted_fields: List[str], ...)`**
75
+ The main entry point for processing a batch of files. It automatically chooses between sequential and parallel processing based on the number of files and configuration.
76
+
77
+ * **files**: An iterable of `Path` objects to process.
78
+ * **ops**: A dictionary mapping field names to operation functions (see `mudio.operations`).
79
+ * **targeted_fields**: A list of fields being modified (used for verification).
80
+ * **max_workers** (int): Number of threads to use (default: CPU count).
81
+ * **dry_run** (bool): If `True`, calculates changes but does not write to disk.
82
+ * **backup_dir** (str): Path to directory for storing backups.
83
+ * **force** (bool): If `True`, overwrites existing backups/files where necessary.
84
+ * **verbose** (bool): Enables progress printing.
85
+ * **filters** (List): A list of filters to apply before processing.
86
+
87
+ **`process_file(path: str, ops: FieldOperationsType, targeted_fields: List[str], ...)`**
88
+ Processes a single file.
89
+ 1. Validates file (permissions, format).
90
+ 2. Applies filters.
91
+ 3. Computes new tag values using `ops`.
92
+ 4. Creates backup (if requested).
93
+ 5. Writes changes.
94
+ 6. Verifies changes by re-reading the file.
95
+
96
+ ### Validation
97
+
98
+ **`validate_file(path: Path) -> Tuple[bool, str]`**
99
+ Performs comprehensive checks:
100
+ * Existence and file type.
101
+ * Read/Write permissions.
102
+ * File size (checks for empty files or files exceeding limits).
103
+ * Format validity (can `mutagen` parse it?).
104
+
105
+ ---
106
+
107
+ ## Operations (`mudio.operations`)
108
+
109
+ This module defines how field values are transformed. It provides the logic for "Set", "Append", "Regex Replace", etc.
110
+
111
+ ### `FieldOperations` Class
112
+
113
+ **`FieldOperations.normalize_values(field_name: str, values: List[str]) -> List[str]`**
114
+ Ensures field values are consistent.
115
+ * **Multi-valued fields** (artist, genre, etc.): Deduplicates values while preserving order (case-insensitive).
116
+ * **Single-valued fields** (title, date, track): Takes only the first value.
117
+
118
+ ### Operation Factories
119
+
120
+ These functions return a callable `op(values: List[str]) -> List[str]` that transforms existing values into new ones.
121
+
122
+ * **`op_overwrite(field, value, delimiter=';')`**: Replaces existing values. Splits strings on `delimiter` for multi-valued fields.
123
+ * **`op_append(field, value, delimiter=';')`**:
124
+ * Single-valued: Appends string.
125
+ * Multi-valued: Adds new item(s) (split by `delimiter`) if not present.
126
+ * **`op_prefix(field, value)`**: Prepends string to values.
127
+ * **`op_find_replace(field, find, replace, regex=False, delimiter=';')`**: Performs string substitution. If result contains `delimiter`, splits into multiple values (for multi-valued fields).
128
+ * **`op_enlist(field, value, delimiter=';')`**: Enlists value(s) (split by `delimiter`) to a multi-valued field list only if it doesn't already exist.
129
+ * **`op_delist(field, value, delimiter=';')`**: Delists (removes) specific value(s) from a multi-valued field.
130
+ * **`op_clear(field)`**: Returns `[""]` (empty string), setting the tag to empty but keeping the key.
131
+ * **`op_delete(field)`**: Returns `[]` (empty list), removing the tag key entirely.
132
+
133
+ > **Note**: Behavior of empty values varies by format. ID3 tags may store empty frames; Vorbis comments typically omit empty values.
134
+
135
+ ---
136
+
137
+ ## Utilities (`mudio.utils`)
138
+
139
+ **`Config`**
140
+ Global configuration settings, loaded from environment variables.
141
+ * `MUDIO_MAX_WORKERS`: Default thread count.
142
+ * `MUDIO_BACKUP_DIR`: Default backup location.
143
+ * `MUDIO_VERBOSE`: Default verbosity.
144
+
145
+ **`get_file_hash(path: Path)`**
146
+ Calculates SHA-256 hash of a file for verification.
147
+
148
+ ---
149
+
150
+ ## Types and Errors
151
+
152
+ ### Error Hierarchy
153
+
154
+ The API defines a hierarchy of exceptions for robust error handling:
155
+
156
+ ```python
157
+ class MudioError(Exception): ...
158
+ class ValidationError(MudioError): ... # Invalid arguments or state
159
+ class FormatError(MudioError): ... # File format issues
160
+ class PermissionError(MudioError): ... # Filesystem permission issues
161
+ class VerificationError(MudioError): ... # Post-write verification failed
162
+ ```
163
+
164
+ ### Type Definitions
165
+
166
+ Common type aliases used in function signatures:
167
+
168
+ ```python
169
+ FieldOperationsType = Dict[str, Callable[[List[str]], List[str]]]
170
+ FieldValuesType = Dict[str, List[str]]
171
+ FilterType = Tuple[str, str, bool]
172
+ ```
173
+
174
+ * **`FieldOperationsType`**: Maps target field names to transformation functions.
175
+ * **`FieldValuesType`**: Standard dictionary for metadata (Field -> List of Strings).