BDM Tool
BDM (Big Dataset Management) Tool is a simple lightweight dataset versioning utility based purely on the file system and symbolic links.
BDM Tool Features:
- No full downloads required: Switch to any dataset version without downloading the entire dataset to your local machine.
- Independent of external VCS: Does not rely on external version control systems like Git or Mercurial, and does not require integrating with one.
- Easy dataset sharing: Supports sharing datasets via remote file systems on a data server.
- Fast version switching: Switching between dataset versions does not require long synchronization processes.
- Transparent version access: Different dataset versions are accessed through simple and intuitive paths (e.g., dataset/v1.0/, dataset/v2.0/, etc.), making versioning fully transparent to configuration files, MLflow parameters, and other tooling.
- Storage optimization: Efficiently stores multiple dataset versions using symbolic links to avoid duplication.
- Designed for large, complex datasets: Well-suited for managing big datasets with intricate directory and subdirectory structures.
- Python API for automation: Provides a simple Python API to automatically create new dataset versions within MLOps pipelines, workflows, ETL jobs, and other automated processes.
General Principles
- Each version of a dataset is a path like
dataset/v1.0/,dataset/v2.0/. - A new dataset version is generated whenever modifications are made
- Each dataset version is immutable and read-only.
- A new version includes only the files that have been added or modified, while unchanged files and directories are stored as symbolic links.
- Each version contains a readme.txt file with a summary of changes.
Intallation
Installation from PyPI (Recommended)
Use pip to install tool by the following command:
pip install bdm-tool
Installation from Sources
Use pip to install tool by the following command:
pip install git+https://github.com/aikho/bdm-tool.git
Usage
Start Versioning Dataset
Let's assume we have a dataset with the following structure:
tree testdata
testdata
├── annotation
│ ├── part01
│ │ ├── regions01.json
│ │ ├── regions02.json
│ │ ├── regions03.json
│ │ ├── regions04.json
│ │ └── regions05.json
│ ├── part02
│ │ ├── regions01.json
│ │ ├── regions02.json
│ │ ├── regions03.json
│ │ ├── regions04.json
│ │ └── regions05.json
│ └── part03
│ ├── regions01.json
│ ├── regions02.json
│ ├── regions03.json
│ ├── regions04.json
│ └── regions05.json
└── data
├── part01
│ ├── image01.png
│ ├── image02.png
│ ├── image03.png
│ ├── image04.png
│ └── image05.png
├── part02
│ ├── image01.png
│ ├── image02.png
│ ├── image03.png
│ ├── image04.png
│ └── image05.png
└── part03
├── image01.png
├── image02.png
├── image03.png
├── image04.png
└── image05.png
9 directories, 30 files
To put it under bdm-tool version control use command bdm init:
bdm init testdata
Version v0.1 of dataset has been created.
Files added: 3, updated: 0, removed: 0, symlinked: 0
The first version v0.1 of the dataset has been created. Let’s take a look at the file structure:
tree testdata
testdata
├── current -> ./v0.1
└── v0.1
├── annotation
│ ├── part01
│ │ ├── regions01.json
│ │ ├── regions02.json
│ │ ├── regions03.json
│ │ ├── regions04.json
│ │ └── regions05.json
│ ├── part02
│ │ ├── regions01.json
│ │ ├── regions02.json
│ │ ├── regions03.json
│ │ ├── regions04.json
│ │ └── regions05.json
│ └── part03
│ ├── regions01.json
│ ├── regions02.json
│ ├── regions03.json
│ ├── regions04.json
│ └── regions05.json
├── data
│ ├── part01
│ │ ├── image01.png
│ │ ├── image02.png
│ │ ├── image03.png
│ │ ├── image04.png
│ │ └── image05.png
│ ├── part02
│ │ ├── image01.png
│ │ ├── image02.png
│ │ ├── image03.png
│ │ ├── image04.png
│ │ └── image05.png
│ └── part03
│ ├── image01.png
│ ├── image02.png
│ ├── image03.png
│ ├── image04.png
│ └── image05.png
└── readme.txt
11 directories, 31 files
We can see that version v0.1 contains all the initial files along with a readme.txt file. Let’s take a look inside readme.txt:
cat testdata/v0.1/readme.txt
Dataset version v0.1 has been created!
Created timestamp: 2023-08-07 19:40:19.498656, OS user: rock-star-ml-engineer
Files added: 2, updated: 0, removed: 0, symlinked: 0
Files added:
annotation/
data/
The file shows the creation date, operating system user, relevant statistics, and a summary of performed operations.
Add New Files
Suppose we have additional data stored in the new_data directory:
tree new_data/
new_data/
├── annotation
│ ├── regions06.json
│ └── regions07.json
└── data
├── image06.png
└── image07.png
2 directories, 4 files
New files can be added to a new dataset version using the dbm change command. Use the --add flag to add individual files, or --add-all to add all files from a specified directory:
bdm change --add_all new_data/annotation/:annotation/part03/ --add_all new_data/data/:data/part03/ -c -m "add new files" testdata
Version v0.2 of dataset has been created.
Files added: 4, updated: 0, removed: 0, symlinked: 14
The : character is used as a separator between the source path and the target subpath inside the dataset where the files should be added.
The -c flag stands for copy. When used, files are copied instead of moved. Moving files can be faster, so you may prefer it for performance reasons.
The -m flag allows you to add a message, which is then stored in the readme.txt file of the new dataset version.
Let’s take a look inside the readme.txt file of the new version:
cat testdata/current/readme.txt
Dataset version v0.2 has been created from previous version v0.1!
add new files
Created timestamp: 2023-08-07 19:38:39.758828, OS user: rock-star-ml-engineer
Files added: 4, updated: 0, removed: 0, symlinked: 14
Files added:
annotation/part03/regions06.json
annotation/part03/regions07.json
data/part03/image06.png
data/part03/image07.png
Next, let’s examine the updated file structure:
tree testdata
testdata
├── current -> ./v0.2
├── v0.1
│ ├── annotation
│ │ ├── part01
│ │ │ ├── regions01.json
│ │ │ ├── regions02.json
│ │ │ ├── regions03.json
│ │ │ ├── regions04.json
│ │ │ └── regions05.json
│ │ ├── part02
│ │ │ ├── regions01.json
│ │ │ ├── regions02.json
│ │ │ ├── regions03.json
│ │ │ ├── regions04.json
│ │ │ └── regions05.json
│ │ └── part03
│ │ ├── regions01.json
│ │ ├── regions02.json
│ │ ├── regions03.json
│ │ ├── regions04.json
│ │ └── regions05.json
│ ├── data
│ │ ├── part01
│ │ │ ├── image01.png
│ │ │ ├── image02.png
│ │ │ ├── image03.png
│ │ │ ├── image04.png
│ │ │ └── image05.png
│ │ ├── part02
│ │ │ ├── image01.png
│ │ │ ├── image02.png
│ │ │ ├── image03.png
│ │ │ ├── image04.png
│ │ │ └── image05.png
│ │ └── part03
│ │ ├── image01.png
│ │ ├── image02.png
│ │ ├── image03.png
│ │ ├── image04.png
│ │ └── image05.png
│ └── readme.txt
└── v0.2
├── annotation
│ ├── part01 -> ../../v0.1/annotation/part01
│ ├── part02 -> ../../v0.1/annotation/part02
│ └── part03
│ ├── regions01.json -> ../../../v0.1/annotation/part03/regions01.json
│ ├── regions02.json -> ../../../v0.1/annotation/part03/regions02.json
│ ├── regions03.json -> ../../../v0.1/annotation/part03/regions03.json
│ ├── regions04.json -> ../../../v0.1/annotation/part03/regions04.json
│ ├── regions05.json -> ../../../v0.1/annotation/part03/regions05.json
│ ├── regions06.json
│ └── regions07.json
├── data
│ ├── part01 -> ../../v0.1/data/part01
│ ├── part02 -> ../../v0.1/data/part02
│ └── part03
│ ├── image01.png -> ../../../v0.1/data/part03/image01.png
│ ├── image02.png -> ../../../v0.1/data/part03/image02.png
│ ├── image03.png -> ../../../v0.1/data/part03/image03.png
│ ├── image04.png -> ../../../v0.1/data/part03/image04.png
│ ├── image05.png -> ../../../v0.1/data/part03/image05.png
│ ├── image06.png
│ └── image07.png
└── readme.txt
20 directories, 46 files
Update Files
Files can be updated in a new dataset version using the dbm change command. Use the --update flag to update individual files, or --update-all to update all files in a given directory:
bdm change --update data_update/regions05.json:annotation/part03/ -c -m "update" testdata
Version v0.3 of dataset has been created.
Files added: 0, updated: 1, removed: 0, symlinked: 9
Let’s take a look inside the readme.txt file of the new version:
cat testdata/current/readme.txt
Dataset version v0.3 has been created from previous version v0.2!
update
Created timestamp: 2023-08-07 19:40:01.753345, OS user: rock-star-data-scientist
Files added: 0, updated: 1, removed: 0, symlinked: 9
Files updated:
annotation/part03/regions05.json
Let’s take a look at the file structure:
tree testdata
testdata
├── current -> ./v0.3
├── v0.1
│ ├── annotation
│ │ ├── part01
│ │ │ ├── regions01.json
│ │ │ ├── regions02.json
│ │ │ ├── regions03.json
│ │ │ ├── regions04.json
│ │ │ └── regions05.json
│ │ ├── part02
│ │ │ ├── regions01.json
│ │ │ ├── regions02.json
│ │ │ ├── regions03.json
│ │ │ ├── regions04.json
│ │ │ └── regions05.json
│ │ └── part03
│ │ ├── regions01.json
│ │ ├── regions02.json
│ │ ├── regions03.json
│ │ ├── regions04.json
│ │ └── regions05.json
│ ├── data
│ │ ├── part01
│ │ │ ├── image01.png
│ │ │ ├── image02.png
│ │ │ ├── image03.png
│ │ │ ├── image04.png
│ │ │ └── image05.png
│ │ ├── part02
│ │ │ ├── image01.png
│ │ │ ├── image02.png
│ │ │ ├── image03.png
│ │ │ ├── image04.png
│ │ │ └── image05.png
│ │ └── part03
│ │ ├── image01.png
│ │ ├── image02.png
│ │ ├── image03.png
│ │ ├── image04.png
│ │ └── image05.png
│ └── readme.txt
├── v0.2
│ ├── annotation
│ │ ├── part01 -> ../../v0.1/annotation/part01
│ │ ├── part02 -> ../../v0.1/annotation/part02
│ │ └── part03
│ │ ├── regions01.json -> ../../../v0.1/annotation/part03/regions01.json
│ │ ├── regions02.json -> ../../../v0.1/annotation/part03/regions02.json
│ │ ├── regions03.json -> ../../../v0.1/annotation/part03/regions03.json
│ │ ├── regions04.json -> ../../../v0.1/annotation/part03/regions04.json
│ │ ├── regions05.json -> ../../../v0.1/annotation/part03/regions05.json
│ │ ├── regions06.json
│ │ └── regions07.json
│ ├── data
│ │ ├── part01 -> ../../v0.1/data/part01
│ │ ├── part02 -> ../../v0.1/data/part02
│ │ └── part03
│ │ ├── image01.png -> ../../../v0.1/data/part03/image01.png
│ │ ├── image02.png -> ../../../v0.1/data/part03/image02.png
│ │ ├── image03.png -> ../../../v0.1/data/part03/image03.png
│ │ ├── image04.png -> ../../../v0.1/data/part03/image04.png
│ │ ├── image05.png -> ../../../v0.1/data/part03/image05.png
│ │ ├── image06.png
│ │ └── image07.png
│ └── readme.txt
└── v0.3
├── annotation
│ ├── part01 -> ../../v0.2/annotation/part01
│ ├── part02 -> ../../v0.2/annotation/part02
│ └── part03
│ ├── regions01.json -> ../../../v0.2/annotation/part03/regions01.json
│ ├── regions02.json -> ../../../v0.2/annotation/part03/regions02.json
│ ├── regions03.json -> ../../../v0.2/annotation/part03/regions03.json
│ ├── regions04.json -> ../../../v0.2/annotation/part03/regions04.json
│ ├── regions05.json
│ ├── regions06.json -> ../../../v0.2/annotation/part03/regions06.json
│ └── regions07.json -> ../../../v0.2/annotation/part03/regions07.json
├── data -> ../v0.2/data
└── readme.txt
26 directories, 54 file
Remove Files
Files or directories can be removed from the dataset using dbm change command with key --remove:
bdm change --remove annotation/part01/regions05.json --remove annotation/part01/regions04.json -c -m "remove obsolete data" testdata
Version v0.4 of dataset has been created.
Files added: 0, updated: 0, removed: 2, symlinked: 8
Combining Operations
Adding, updating, and removing operations can be freely combined within a single dataset version. Use bdm change -h command to get detailed information on available keys and options:
bdm change -h
License
See LICENSE file in the repo.
Metadata
Release files for bdm-tool 0.2
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | Provenance | |
|---|---|---|---|---|
| bdm_tool-0.2.tar.gz | 11.9 kB | Without provenance | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| bdm_tool-0.2-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 22.2 kB
Release files / bdm_tool-0.2.tar.gz
| Download URL | bdm_tool-0.2.tar.gz |
|---|---|
| Size | 11.9 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
a7a9e2d4aa835ebba8a5df2e8367a3ab21b453c5f1a0a928304157dc1356ace6
|
|
BLAKE2b-256 checksum How to use checksums |
8861bb37c300f2038ee60ab08a9846c698d857f782f0d67fe7124189b8327ea9
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Release files / bdm_tool-0.2-py3-none-any.whl
| Download URL | bdm_tool-0.2-py3-none-any.whl |
|---|---|
| Size | 10.2 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
07ead409758650b1071c71c9c998de9021ea7d59049c7641b848b1b6d3b239ee
|
|
BLAKE2b-256 checksum How to use checksums |
8addb04d53c1a390202304f50b57862b431707f3c5ba72a227eb6de8e6a2ec45
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.11.13
|
Security for bdm-tool 0.2
Provenance
Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.
No provenance found
None of the files in this release were uploaded with provenance metadata.
A note on package security
PyPI is a repository for distributing packages, not a service for auditing them. While third-party security researchers and our staff do their best to detect and remove malicious packages, PyPI cannot guarantee the quality, security or suitability of any given package.