py-file-versioning
A flexible file versioning system with compression support, written in Python.
Table of Contents
Features
- Create versioned backups of files with automatic sequence numbering
- Multiple compression options: gzip, bzip2, xz, or uncompressed
- Configurable timestamp formats (UTC or local time)
- Limit the number of versions kept per file
- Command-line interface for easy integration
- Support for Unicode filenames
- Cross-platform compatibility
Package Name Convention
While the package is installed as py-file-versioning (using hyphens), you should use py_file_versioning (using underscores) in your Python imports following Python naming conventions.
Installation
From PyPI
pip install py-file-versioning
From Source
git clone https://github.com/jftuga/py-file-versioning.git
cd py-file-versioning
pip install .
For development installation:
uv venv
source .venv/bin/activate
uv pip install -e '.[dev]'
uv pip list
Command Line Usage
The package installs a command-line tool called pyfileversioning. Here are some common operations:
Create a version:
pyfileversioning create myfile.txt
Create a compressed version:
pyfileversioning create myfile.txt -c gz # or --compression gz
List all versions:
pyfileversioning list myfile.txt
Restore a specific version to a new file path:
pyfileversioning restore versions/myfile--20240120.123456_001.txt.gz --target /path/to/restored_file.txt
Remove a version:
pyfileversioning remove versions/myfile--20240120.123456_001.txt.gz
Demo Shell Session
Here's a practical demonstration of using the command-line interface:
# Create a sample config file
$ echo "database_host=localhost" > config.ini
$ cat config.ini
database_host=localhost
# Create first version (uncompressed)
$ pyfileversioning create config.ini -d backups
Created version: backups/config--20250207.044841_001--loc_mod.ini
# Update the file content
$ echo "database_port=5432" >> config.ini
# Create compressed version
$ pyfileversioning create config.ini -d backups -c gz
Created version: backups/config--20250207.044924_001--loc_mod.ini.gz
# List all versions
$ pyfileversioning list config.ini -d backups
Path | Sequence | Size | Timestamp | TimeZone | TimestampSrc
==== | ======== | ==== | ========= | ======== | ============
config--20250207.044924_001--loc_mod.ini.gz | 1 | 95 | 2025-02-07T04:49:24 | local | modify time
config--20250207.044841_001--loc_mod.ini | 1 | 24 | 2025-02-07T04:48:41 | local | modify time
# Add more content and create another version with UTC time
$ echo "database_name=myapp" >> config.ini
$ pyfileversioning create config.ini -d backups -c gz -u
Created version: backups/config--20250207.095009_001--utc_mod.ini.gz
# View all versions with size and timestamp (note: mixed timezone versions not recommended)
$ pyfileversioning list config.ini -d backups
Path | Sequence | Size | Timestamp | TimeZone | TimestampSrc
==== | ======== | ==== | ========= | ======== | ============
config--20250207.095009_001--utc_mod.ini.gz | 1 | 107 | 2025-02-07T09:50:09 | utc | modify time
config--20250207.044924_001--loc_mod.ini.gz | 1 | 95 | 2025-02-07T04:49:24 | local | modify time
config--20250207.044841_001--loc_mod.ini | 1 | 24 | 2025-02-07T04:48:41 | local | modify time
Python API Usage
The library provides a flexible API for file versioning. Here's how to use it:
from py_file_versioning import FileVersioning, FileVersioningConfig
# Create a test file
def create_example_file(filename: str) -> None:
content = """
# Database configuration settings
db_host = db.example.com
db_port = 5432
db_name = production_db
""".strip()
with open(filename, 'w') as f:
f.write(content)
# Basic usage
filename = "example.ini"
create_example_file(filename)
versioning = FileVersioning()
version_path, removed, error = versioning.create_version(filename)
if error:
print(f"Warning: {error}")
print(version_path)
# Advanced configuration
config = FileVersioningConfig(
versions_path="backups", # Store versions in 'backups' directory
compression="gz", # Use gzip compression
max_versions=5, # Keep only last 5 versions
use_utc=True, # Use UTC timestamps
use_modified_time=True, # Use file's modified time
delimiter="__" # Custom delimiter for version files
)
versioning = FileVersioning(config)
version_path, removed, error = versioning.create_version(filename)
if error:
print(f"Warning: {error}")
print(version_path)
Configuration Options
FileVersioningConfig Parameters
| Parameter | Type | Default | Description |
|---|---|---|---|
| delimiter | str | "--" | Separator between filename and version information |
| use_utc | bool | False | Use UTC timestamps instead of local time |
| versions_path | str | "versions" | Directory to store versions |
| compression | str | "none" | Compression type: "none", "gz", "bz2", "xz" |
| max_versions | Optional[int] | None | Maximum number of versions to keep |
| use_modified_time | bool | True | Use file's modified time instead of current time |
Command Line Options
usage: pyfileversioning [-h] [-V] [-t TARGET] [-d VERSIONS_PATH]
[-c {none,gz,bz2,xz}] [-m MAX_VERSIONS] [-s {mod,sto}]
[-u] [-D DELIMITER]
[{create,restore,list,remove}] files [files ...]
Options:
-V, --version: Show version information-t, --target: Target file path for restore operation (must be full path to the restored file)-d, --versions-path: Directory to store versions (default: versions)-c, --compression: Compression type to use (none, gz, bz2, xz)-m, --max-versions: Maximum number of versions to keep-s, --src: Source for timestamps (mod: file modified time, sto: current time)-u, --utc: Use UTC timezone for timestamps (default: local time)--delimiter DELIMITER: The delimiter to use (default: --)
Environment Variables:
PFV_VERSIONS_PATH: Override default versions directoryPFV_COMPRESSION: Override default compression typePFV_DELIMITER: Override default delimiter
Notes:
- The tool supports file patterns (e.g.,
*.txt,config*.ini) - Multiple files can be specified for batch operations
Examples
Maintaining Multiple Versions
from py_file_versioning import FileVersioning, FileVersioningConfig
# Create versions with different timezone and timestamp combinations
configs = [
# Local timezone versions
{"use_utc": False, "use_modified_time": True, "desc": "local timezone, modified time"},
{"use_utc": False, "use_modified_time": False, "desc": "local timezone, current time"},
# UTC timezone versions
{"use_utc": True, "use_modified_time": True, "desc": "UTC timezone, modified time"},
{"use_utc": True, "use_modified_time": False, "desc": "UTC timezone, current time"}
]
for cfg in configs:
config = FileVersioningConfig(
use_utc=cfg["use_utc"],
use_modified_time=cfg["use_modified_time"]
)
versioning = FileVersioning(config)
version_path, removed, error = versioning.create_version("example.ini")
print(version_path)
Using Different Compression Types
from py_file_versioning import FileVersioning, FileVersioningConfig
# Create versions using each compression type
compression_types = ["gz", "bz2", "xz"]
for compression in compression_types:
config = FileVersioningConfig(
compression=compression,
use_utc=True, # Use UTC time
use_modified_time=True # Use file's modified time
)
versioning = FileVersioning(config)
version_path, removed, error = versioning.create_version("example.ini")
print(version_path)
Version File Naming
Version files follow this naming pattern:
{original_name}{delimiter}{timestamp}_{sequence}{delimiter}{version_spec}{extension}[.compression_ext]
Example:
myfile--20240120.123456_001--utc_mod.txt.gz
Where:
myfileis the original filename--is the delimiter (configurable)20240120.123456is the timestamp (YYYYMMDD.HHMMSS)001is the sequence numberutc_modis the version specification:- First part (
utcorloc) indicates timezone (UTC or local) - Second part (
modorsto) indicates timestamp source (modified time or stored/current time)
- First part (
.txtis the original extension.gzis the compression extension (if compression is used)
Note: All versions of a file must use consistent timezone and timestamp source settings.
Development
Setting Up Development Environment
# Clone the repository
git clone https://github.com/jftuga/py-file-versioning.git
cd py-file-versioning
# Create and activate virtual environment
python -m venv .venv
source .venv/bin/activate # On Windows: .venv\Scripts\activate
# Install development dependencies
pip install -e '.[dev]'
Running Tests
pytest
For coverage report:
pytest --cov=file_versioning --cov-report=html
Code Quality Checks
# Format code
black .
# Sort imports
isort .
# Style checking
flake8
# Linting
ruff check
License
This project is licensed under the MIT License - see the LICENSE file for details.
Metadata
Release files for py-file-versioning 0.10.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| py_file_versioning-0.10.0-py3-none-any.whl | Python 3 | none | any | Details |
Release files / py_file_versioning-0.10.0-py3-none-any.whl
| Download URL | py_file_versioning-0.10.0-py3-none-any.whl |
|---|---|
| Size | 16.8 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
eec3f40044def2d738eb8732b2eb578b748bbe688fafd285df3af077178510d2
|
|
BLAKE2b-256 checksum How to use checksums |
7f234f56f163ca56a49f1576e2a0f43df9df2a21860131a8f883c7836b63087f
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.1.0 CPython/3.12.8
|