Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ dftt_timecode.egg-info
.pytest_cache
.DS_Store
playground.ipynb
CLAUDE.md
dist
build
.claude/settings.local.json
8 changes: 7 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0

## [Unreleased]

## [1.0.0b4]
## [1.0.0] - 2026-05-12

### Summary

First stable release. The library graduates from beta with the breaking changes accumulated during the `1.0.0b*` series finalized. Downstream code that worked against `1.0.0b4` should require no further changes.

首个正式版本。库从测试版毕业,`1.0.0b*` 系列累积的破坏性变更在此版本定稿。已适配 `1.0.0b4` 的下游代码无需进一步修改。

### Fixed

Expand Down
184 changes: 184 additions & 0 deletions CLAUDE.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,184 @@
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Development Commands

### Package Management
- **Recommended:** Use `uv` package manager (used in CI/CD)
- Install dependencies: `uv sync`
- Run commands with dependencies: `uv run <command>`
- **Alternative:** Traditional pip
- Install in development mode: `pip install -e .`
- Install dev dependencies: `pip install -e .[dev]` (requires pyproject.toml dependency groups)

### Testing
- Run all tests: `pytest` or `uv run pytest`
- Run with verbose output: `pytest -v -s` (configured in pyproject.toml)
- Run specific test file: `pytest test/test_dftt_timecode.py`
- Run specific test for TimeRange: `pytest test/test_dftt_timerange.py`

### Documentation
- Build docs: `cd docs && make html` or `cd docs && uv run make html`
- Clean build: `cd docs && make clean`
- View docs: Open `docs/_build/html/index.html`
- **Note:** Documentation uses Sphinx with MyST-Parser for Markdown support

### Building and Publishing
- Build package: `uv build`
- Publishing is automated via GitHub Actions on release creation

## Code Structure

This is a Python timecode library for the film and TV industry with high frame rate support.

### Package Organization
```
dftt_timecode/
├── core/
│ ├── dftt_timecode.py # Core DfttTimecode class
│ └── dftt_timerange.py # DfttTimeRange class for time intervals
├── pattern.py # Regex patterns for all timecode formats
├── error.py # Custom exception classes
├── logging_config.py # Logging setup with branch-aware default levels
└── __init__.py # Package exports and convenience aliases
```

### Main Components

#### DfttTimecode Class (`dftt_timecode/core/dftt_timecode.py`)
- Core timecode class with all timecode operations
- Handles format conversion, arithmetic, and comparison operations
- Uses `fractions.Fraction` for high-precision internal timestamp storage

#### DfttTimeRange Class (`dftt_timecode/core/dftt_timerange.py`)
- Handles time intervals with start and end timecodes
- Supports range operations: intersection, union, containment checks
- Calculates duration and frame counts for ranges

#### Pattern Module (`dftt_timecode/pattern.py`)
- Contains regex patterns for all supported timecode formats
- Validates input strings before parsing
- Formats: SMPTE, SRT, FFMPEG, FCPX, DLP, frame count, timestamps

#### Error Module (`dftt_timecode/error.py`)
- Custom exception classes for timecode-specific errors, all inheriting from `DFTTError`
- Timecode errors: `DFTTTimecodeValueError`, `DFTTTimecodeInitializationError`, `DFTTTimecodeTypeError`, `DFTTTimecodeOperatorError`
- TimeRange errors: `DFTTTimeRangeMethodError`, `DFTTTimeRangeValueError`, `DFTTTimeRangeTypeError`, `DFTTTimeRangeFPSError`

#### Logging Module (`dftt_timecode/logging_config.py`)
- Provides `get_logger(name)` and `configure_logging(level)` (both re-exported at package level)
- Default level is branch-aware: `INFO` for installed packages and `main` branch, `DEBUG` for dev/feature branches
- Override via `DFTT_LOG_LEVEL` environment variable (`DEBUG`/`INFO`/`WARNING`/`ERROR`/`CRITICAL`)

### Key Features
- **Multiple formats:** SMPTE (DF/NDF), SRT, FFMPEG, FCPX, DLP, frame count, timestamps
- **High frame rate:** 0.01-999.99 fps support
- **Strict mode:** 24-hour cycling for broadcast workflows
- **Rich operators:** Full arithmetic (+, -, *, /) and comparison (==, !=, <, >, <=, >=)
- **High precision:** Internal Fraction-based calculations for lossless accuracy
- **Convenience aliases:** `dtc` / `Timecode` (DfttTimecode), `dtr` / `Timerange` (DfttTimeRange)

### Timecode Types Supported
- `smpte`: Standard SMPTE format (01:23:45:12 or 01:23:45;12 for drop-frame)
- `srt`: SubRip format (01:23:45,678)
- `ffmpeg`: FFmpeg format (01:23:45.67)
- `fcpx`: Final Cut Pro X format (1/24s)
- `dlp`: DLP Cinema format (01:23:45:102)
- `frame`: Frame count (1000f)
- `time`: Timestamp in seconds (3600.0s)
- `auto`: Automatic detection based on input format

### Architecture Patterns
- **Single-dispatch methods:** Uses `functools.singledispatchmethod` for handling different input types
- **Input validation:** Comprehensive regex-based validation via pattern.py
- **Internal storage:** High-precision Fraction timestamps (no floating-point errors)
- **Lazy evaluation:** Format conversions computed on-demand
- **Immutability:** Operations return new instances rather than modifying in place

### Testing
- Uses pytest framework with parametrized tests
- Test files: `test/test_dftt_timecode.py`, `test/test_dftt_timerange.py`, `test/test_logging_config.py`
- Covers multiple timecode formats, edge cases, and error conditions
- Fixture-based test data setup

### Documentation System
- Sphinx with MyST-Parser (supports both RST and Markdown)
- Auto-generated API docs from docstrings
- Deployed to GitHub Pages via `.github/workflows/docs.yml`
- Changelog: Maintained in `CHANGELOG.md` (Keep a Changelog format), included in docs via RST
- Internationalization: Chinese translations under `docs/locale/`, built with `sphinx-intl`

### CI/CD Workflows
- **Documentation:** Builds and deploys to GitHub Pages on push to main (`.github/workflows/docs.yml`)
- **Publishing:** Automatically publishes to PyPI on GitHub release creation (`.github/workflows/publish-to-pypi.yml`)

## Version Information
- Current version: 1.0.0
- Python requirement: >=3.11
- Main dependencies: All standard library (fractions, logging, math, functools, re, subprocess)
- Dev dependencies: pytest, sphinx, pydata-sphinx-theme, myst-parser, sphinx-intl

## Common Usage Patterns

### Basic Timecode Creation
```python
from dftt_timecode import DfttTimecode, dtc

# Full class name
tc = DfttTimecode('01:00:00:00', 'auto', fps=24, drop_frame=False, strict=True)

# Using convenience alias
tc = dtc('01:00:00:00', fps=24)

# Access properties
tc.type # timecode format type
tc.fps # frame rate
tc.framecount # total frames from zero
tc.timestamp # seconds from zero (float)
tc.precise_timestamp # high-precision Fraction timestamp
```

### Format Conversion
```python
# Convert output format
tc.timecode_output('srt') # SubRip format
tc.timecode_output('ffmpeg') # FFmpeg format

# Change timecode type
tc.set_type('smpte')
tc.set_fps(30, rounding=True)
tc.set_strict(False)
```

### Arithmetic Operations
```python
result = tc1 + tc2 # add timecodes
result = tc - 100 # subtract 100 frames
result = tc * 2 # multiply by factor
result = tc / 2 # divide by factor
result = tc + 1.0 # add 1 second (float)

# Comparisons
tc1 > tc2 # compare timecodes
tc1 == tc2 # equality check
```

### TimeRange Operations
```python
from dftt_timecode import DfttTimeRange, dtr

# Create time range
tr = DfttTimeRange(start_tc='01:00:00:00', end_tc='02:00:00:00', fps=24)
# or using alias
tr = dtr('01:00:00:00', '02:00:00:00', fps=24)

# Access properties
tr.duration # duration as DfttTimecode
tr.framecount # total frames in range

# Range operations
tr1.intersection(tr2) # overlapping portion
tr1.union(tr2) # combined range
tc in tr # check if timecode is in range
```
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# DFTT Timecode

[![pypi](https://img.shields.io/badge/pypi-0.0.14-brightgreen)](https://pypi.org/project/dftt-timecode/)
[![pypi](https://img.shields.io/pypi/v/dftt-timecode.svg)](https://pypi.org/project/dftt-timecode/)
[![python](https://img.shields.io/badge/python-3.11+-blue)](https://www.python.org/)
[![GitHub license](https://img.shields.io/badge/license-LGPL2.1-green)](https://github.com/OwenYou/dftt_timecode/blob/main/LICENSE)
[![Documentation](https://img.shields.io/badge/docs-GitHub%20Pages-blue)](https://owenyou.github.io/dftt_timecode/)
Expand Down
4 changes: 2 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ build-backend = "uv_build"

[project]
name = "dftt-timecode"
version = "1.0.0b4"
version = "1.0.0"
description = "Timecode library for film and TV industry, supports HFR and a bunch of cool features"
readme = "README.md"
requires-python = ">=3.11"
Expand All @@ -17,7 +17,7 @@ classifiers = [
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.11",
"Programming Language :: Python :: 3.12",
"Development Status :: 4 - Beta",
"Development Status :: 5 - Production/Stable",
"Natural Language :: Chinese (Simplified)",
"Operating System :: OS Independent",
]
Expand Down
2 changes: 1 addition & 1 deletion uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading