video-extensions 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.
- video_extensions-1.0.0/.github/FUNDING.yml +4 -0
- video_extensions-1.0.0/.github/workflows/publish.yml +34 -0
- video_extensions-1.0.0/.github/workflows/test.yml +30 -0
- video_extensions-1.0.0/.gitignore +11 -0
- video_extensions-1.0.0/.python-version +1 -0
- video_extensions-1.0.0/CHANGELOG.md +29 -0
- video_extensions-1.0.0/CONTRIBUTING.md +143 -0
- video_extensions-1.0.0/LICENSE +21 -0
- video_extensions-1.0.0/PKG-INFO +149 -0
- video_extensions-1.0.0/README.md +120 -0
- video_extensions-1.0.0/pyproject.toml +63 -0
- video_extensions-1.0.0/tests/__init__.py +0 -0
- video_extensions-1.0.0/tests/_data.py +26 -0
- video_extensions-1.0.0/tests/test_constants.py +15 -0
- video_extensions-1.0.0/tests/test_integration.py +23 -0
- video_extensions-1.0.0/tests/test_is_video_extension.py +24 -0
- video_extensions-1.0.0/tests/test_is_video_path.py +43 -0
- video_extensions-1.0.0/uv.lock +256 -0
- video_extensions-1.0.0/video_extensions/__init__.py +42 -0
- video_extensions-1.0.0/video_extensions/_data.py +38 -0
- video_extensions-1.0.0/video_extensions/py.typed +0 -0
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
name: "Publish"
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
tags:
|
|
6
|
+
# Publish on any tag starting with a `v`, e.g., v0.1.0
|
|
7
|
+
- v*
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
run:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
environment:
|
|
13
|
+
name: pypi
|
|
14
|
+
permissions:
|
|
15
|
+
id-token: write
|
|
16
|
+
contents: write
|
|
17
|
+
steps:
|
|
18
|
+
- name: Checkout
|
|
19
|
+
uses: actions/checkout@v5
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v6
|
|
22
|
+
- name: Install Python 3.8
|
|
23
|
+
run: uv python install 3.8
|
|
24
|
+
- name: Build
|
|
25
|
+
run: uv build
|
|
26
|
+
- name: Publish
|
|
27
|
+
run: uv publish
|
|
28
|
+
- name: Create GitHub Release
|
|
29
|
+
uses: softprops/action-gh-release@v2
|
|
30
|
+
with:
|
|
31
|
+
tag_name: ${{ github.ref_name }}
|
|
32
|
+
name: Release ${{ github.ref_name }}
|
|
33
|
+
env:
|
|
34
|
+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
name: Tests
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
push:
|
|
5
|
+
branches: [main]
|
|
6
|
+
pull_request:
|
|
7
|
+
branches: [main]
|
|
8
|
+
|
|
9
|
+
jobs:
|
|
10
|
+
test:
|
|
11
|
+
runs-on: ubuntu-latest
|
|
12
|
+
strategy:
|
|
13
|
+
matrix:
|
|
14
|
+
python-version: ["3.8", "3.9", "3.10", "3.11", "3.12"]
|
|
15
|
+
|
|
16
|
+
steps:
|
|
17
|
+
- name: Checkout
|
|
18
|
+
uses: actions/checkout@v5
|
|
19
|
+
|
|
20
|
+
- name: Install uv
|
|
21
|
+
uses: astral-sh/setup-uv@v6
|
|
22
|
+
|
|
23
|
+
- name: Set up Python ${{ matrix.python-version }}
|
|
24
|
+
run: uv python install ${{ matrix.python-version }}
|
|
25
|
+
|
|
26
|
+
- name: Install dependencies
|
|
27
|
+
run: uv sync --group dev
|
|
28
|
+
|
|
29
|
+
- name: Run tests
|
|
30
|
+
run: uv run pytest
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
3.8
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0]
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
- Initial release of video-extensions Python package
|
|
12
|
+
- `is_video_extension()` function to check if a file extension is a video type
|
|
13
|
+
- `is_video_path()` function to check if a file path has a video extension
|
|
14
|
+
- `VIDEO_EXTENSIONS` frozenset containing 36 known video file extensions
|
|
15
|
+
- `VIDEO_EXTENSIONS_LOWER` constant containing all video extensions in lowercase for optimized case-insensitive lookups
|
|
16
|
+
- Support for case-insensitive extension checks
|
|
17
|
+
- Dot-aware extension handling (supports both "mp4" and ".mp4" formats)
|
|
18
|
+
- Dotfile support in `is_video_path()` function - now handles files like `.mov` where the entire filename (without leading dot) is treated as the extension
|
|
19
|
+
- Comprehensive test suite with unit and integration tests
|
|
20
|
+
- Type hints for better IDE support and type checking
|
|
21
|
+
- Zero dependencies for minimal overhead
|
|
22
|
+
|
|
23
|
+
### Features
|
|
24
|
+
- Immutable collection of 36 known video file extensions
|
|
25
|
+
- Fast membership checks using `frozenset`
|
|
26
|
+
- Support for common formats (mp4, mov, avi, mkv, webm), streaming formats (m3u8, m4v), professional formats (mxf, aaf), and more
|
|
27
|
+
- Python 3.8+ compatibility
|
|
28
|
+
|
|
29
|
+
[1.0.0]: https://github.com/ysskrishna/video-extensions/releases/tag/v1.0.0
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Contributing to video-extensions
|
|
2
|
+
|
|
3
|
+
Thank you for your interest in contributing to `video-extensions`! This document provides guidelines and instructions for contributing.
|
|
4
|
+
|
|
5
|
+
## Getting Started
|
|
6
|
+
|
|
7
|
+
### Prerequisites
|
|
8
|
+
|
|
9
|
+
- Python 3.8 or higher
|
|
10
|
+
- [uv](https://github.com/astral-sh/uv)
|
|
11
|
+
|
|
12
|
+
### Setting Up the Development Environment
|
|
13
|
+
|
|
14
|
+
1. **Clone the repository**:
|
|
15
|
+
```bash
|
|
16
|
+
git clone https://github.com/ysskrishna/video-extensions.git
|
|
17
|
+
cd video-extensions
|
|
18
|
+
```
|
|
19
|
+
|
|
20
|
+
2. **Install dependencies**:
|
|
21
|
+
```bash
|
|
22
|
+
uv sync --group dev
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
3. **Verify the setup**:
|
|
26
|
+
```bash
|
|
27
|
+
uv run pytest
|
|
28
|
+
```
|
|
29
|
+
|
|
30
|
+
## Development Workflow
|
|
31
|
+
|
|
32
|
+
### Running Tests
|
|
33
|
+
|
|
34
|
+
Run the test suite to ensure everything works:
|
|
35
|
+
|
|
36
|
+
```bash
|
|
37
|
+
uv run pytest
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
Run a specific test file:
|
|
41
|
+
|
|
42
|
+
```bash
|
|
43
|
+
uv run pytest tests/test_is_video_extension.py
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
### Code Style
|
|
47
|
+
|
|
48
|
+
- Follow [PEP 8](https://pep8.org/) style guidelines
|
|
49
|
+
- Use type hints for all function parameters and return values
|
|
50
|
+
- Keep functions simple and focused
|
|
51
|
+
- Add docstrings to all public functions
|
|
52
|
+
|
|
53
|
+
### Adding New Video Extensions
|
|
54
|
+
|
|
55
|
+
If you want to add new video extensions to the list:
|
|
56
|
+
|
|
57
|
+
1. Edit `video_extensions/_data.py`
|
|
58
|
+
2. Add the extension (lowercase, without leading dot) to the `VIDEO_EXTENSIONS` frozenset
|
|
59
|
+
3. Add corresponding test cases in the test files
|
|
60
|
+
4. Run the test suite to ensure everything passes
|
|
61
|
+
|
|
62
|
+
### Writing Tests
|
|
63
|
+
|
|
64
|
+
- All new features should include tests
|
|
65
|
+
- Tests should be placed in the `tests/` directory
|
|
66
|
+
|
|
67
|
+
## Submitting Changes
|
|
68
|
+
|
|
69
|
+
### Pull Request Process
|
|
70
|
+
|
|
71
|
+
1. **Create a branch**:
|
|
72
|
+
```bash
|
|
73
|
+
git checkout -b feature/your-feature-name
|
|
74
|
+
# or
|
|
75
|
+
git checkout -b fix/your-fix-name
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
2. **Make your changes**:
|
|
79
|
+
- Write your code
|
|
80
|
+
- Add tests for new functionality
|
|
81
|
+
- Ensure all tests pass
|
|
82
|
+
- Update documentation if needed
|
|
83
|
+
|
|
84
|
+
3. **Commit your changes**:
|
|
85
|
+
```bash
|
|
86
|
+
git add .
|
|
87
|
+
git commit -m "Description of your changes"
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
Use clear, descriptive commit messages. Follow the format:
|
|
91
|
+
- `feat: add new feature`
|
|
92
|
+
- `fix: fix bug description`
|
|
93
|
+
- `docs: update documentation`
|
|
94
|
+
- `test: add tests for feature`
|
|
95
|
+
|
|
96
|
+
4. **Push to your fork**:
|
|
97
|
+
```bash
|
|
98
|
+
git push origin feature/your-feature-name
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
5. **Create a Pull Request**:
|
|
102
|
+
- Go to the repository on GitHub
|
|
103
|
+
- Click "New Pull Request"
|
|
104
|
+
- Select your branch
|
|
105
|
+
- Fill out the PR template with:
|
|
106
|
+
- Description of changes
|
|
107
|
+
- Related issues (if any)
|
|
108
|
+
- Testing instructions
|
|
109
|
+
|
|
110
|
+
### Pull Request Guidelines
|
|
111
|
+
|
|
112
|
+
- Keep PRs focused on a single feature or fix
|
|
113
|
+
- Ensure all tests pass
|
|
114
|
+
- Update documentation if you're adding new features
|
|
115
|
+
- Write clear commit messages
|
|
116
|
+
- Reference any related issues
|
|
117
|
+
|
|
118
|
+
## Reporting Issues
|
|
119
|
+
|
|
120
|
+
When reporting issues, please include:
|
|
121
|
+
|
|
122
|
+
- Python version
|
|
123
|
+
- Package version
|
|
124
|
+
- Steps to reproduce
|
|
125
|
+
- Expected behavior
|
|
126
|
+
- Actual behavior
|
|
127
|
+
- Any relevant error messages or stack traces
|
|
128
|
+
|
|
129
|
+
## Code of Conduct
|
|
130
|
+
|
|
131
|
+
- Be respectful and considerate
|
|
132
|
+
- Welcome newcomers and help them learn
|
|
133
|
+
- Focus on constructive feedback
|
|
134
|
+
- Be open to feedback and suggestions
|
|
135
|
+
|
|
136
|
+
## Questions?
|
|
137
|
+
|
|
138
|
+
If you have questions about contributing, feel free to:
|
|
139
|
+
|
|
140
|
+
- Open an issue on GitHub
|
|
141
|
+
- Check existing issues and discussions
|
|
142
|
+
|
|
143
|
+
Thank you for contributing to `video-extensions`! 🎉
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Y. Siva Sai Krishna
|
|
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.
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: video-extensions
|
|
3
|
+
Version: 1.0.0
|
|
4
|
+
Summary: Check if a file or extension is a video type, and iterate over 36 known video file formats including mp4, mov, avi, mkv, and more. Python port of video-extensions npm package.
|
|
5
|
+
Project-URL: Homepage, https://github.com/ysskrishna/video-extensions
|
|
6
|
+
Project-URL: Repository, https://github.com/ysskrishna/video-extensions.git
|
|
7
|
+
Project-URL: Issues, https://github.com/ysskrishna/video-extensions/issues
|
|
8
|
+
Project-URL: Changelog, https://github.com/ysskrishna/video-extensions/blob/main/CHANGELOG.md
|
|
9
|
+
Project-URL: Discussions, https://github.com/ysskrishna/video-extensions/discussions
|
|
10
|
+
Author-email: ysskrishna <sivasaikrishnassk@gmail.com>
|
|
11
|
+
License: MIT
|
|
12
|
+
License-File: LICENSE
|
|
13
|
+
Keywords: extension,extensions,file,file-detection,file-extensions,file-type,file-utils,mime-type,mit license,utilities,utils,video,video-detection,video-files,ysskrishna
|
|
14
|
+
Classifier: Development Status :: 5 - Production/Stable
|
|
15
|
+
Classifier: Intended Audience :: Developers
|
|
16
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.8
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.9
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
24
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
25
|
+
Classifier: Topic :: Utilities
|
|
26
|
+
Classifier: Typing :: Typed
|
|
27
|
+
Requires-Python: >=3.8
|
|
28
|
+
Description-Content-Type: text/markdown
|
|
29
|
+
|
|
30
|
+
# Video Extensions
|
|
31
|
+
|
|
32
|
+
[](https://www.python.org/downloads/)
|
|
33
|
+
[](https://github.com/ysskrishna/video-extensions/blob/main/LICENSE)
|
|
34
|
+

|
|
35
|
+
[](https://pypi.org/project/video-extensions/)
|
|
36
|
+
[](https://pepy.tech/projects/video-extensions)
|
|
37
|
+
|
|
38
|
+
Check if a file or extension is a video type, and iterate over 36 known video file formats including mp4, mov, avi, mkv, and more. Python port of [video-extensions](https://github.com/sindresorhus/video-extensions) npm package.
|
|
39
|
+
|
|
40
|
+
## Features
|
|
41
|
+
|
|
42
|
+
- Immutable collection of 36 known video file extensions
|
|
43
|
+
- Fast membership checks using `frozenset`
|
|
44
|
+
- Case-insensitive and dot-aware checks
|
|
45
|
+
- Works for both extensions and full file paths
|
|
46
|
+
- Supports dotfiles (e.g., `.mov`)
|
|
47
|
+
- Zero dependencies, minimal overhead
|
|
48
|
+
|
|
49
|
+
## Installation
|
|
50
|
+
|
|
51
|
+
```bash
|
|
52
|
+
pip install video-extensions
|
|
53
|
+
```
|
|
54
|
+
|
|
55
|
+
Or using `uv`:
|
|
56
|
+
|
|
57
|
+
```bash
|
|
58
|
+
uv add video-extensions
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
## Usage
|
|
62
|
+
|
|
63
|
+
### Check if an extension is a video type
|
|
64
|
+
|
|
65
|
+
```python
|
|
66
|
+
from video_extensions import is_video_extension
|
|
67
|
+
|
|
68
|
+
is_video_extension("mp4") # True
|
|
69
|
+
is_video_extension(".mov") # True (dot-aware)
|
|
70
|
+
is_video_extension("AVI") # True (case-insensitive)
|
|
71
|
+
is_video_extension("txt") # False
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
### Check if a file path has a video extension
|
|
75
|
+
|
|
76
|
+
```python
|
|
77
|
+
from video_extensions import is_video_path
|
|
78
|
+
|
|
79
|
+
is_video_path("movie.mp4") # True
|
|
80
|
+
is_video_path("/path/to/video.MOV") # True (case-insensitive)
|
|
81
|
+
is_video_path("presentation.avi") # True
|
|
82
|
+
is_video_path("document.txt") # False
|
|
83
|
+
is_video_path(".mov") # True (dotfile support)
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Access the list of video extensions
|
|
87
|
+
|
|
88
|
+
```python
|
|
89
|
+
from video_extensions import VIDEO_EXTENSIONS, VIDEO_EXTENSIONS_LOWER
|
|
90
|
+
|
|
91
|
+
# VIDEO_EXTENSIONS is a frozenset of all known video extensions
|
|
92
|
+
print(len(VIDEO_EXTENSIONS)) # 36
|
|
93
|
+
"mp4" in VIDEO_EXTENSIONS # True
|
|
94
|
+
"txt" in VIDEO_EXTENSIONS # False
|
|
95
|
+
|
|
96
|
+
# VIDEO_EXTENSIONS_LOWER contains all extensions in lowercase
|
|
97
|
+
# Useful for case-insensitive lookups without calling .lower() repeatedly
|
|
98
|
+
"MP4" in VIDEO_EXTENSIONS_LOWER # True (case-insensitive)
|
|
99
|
+
|
|
100
|
+
# Iterate over all extensions
|
|
101
|
+
for ext in sorted(VIDEO_EXTENSIONS):
|
|
102
|
+
print(ext)
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
## Supported Extensions
|
|
106
|
+
|
|
107
|
+
The package includes support for 36 video file extensions:
|
|
108
|
+
|
|
109
|
+
- **Common formats**: mp4, mov, avi, mkv, webm, flv, wmv, mpg, mpeg
|
|
110
|
+
- **Streaming**: m3u8, m4v, m4p, ogv, ogg
|
|
111
|
+
- **Professional**: mxf, drc, aaf, roq
|
|
112
|
+
- **Legacy**: 3gp, 3g2, asf, vob, rm, rmvb, qt
|
|
113
|
+
- **Specialized**: avchd, m2v, mp2, mpe, mpv, mng, nsv, svi, yuv, wmv
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
## Contributing
|
|
117
|
+
|
|
118
|
+
Contributions are welcome! Please read our [Contributing Guide](https://github.com/ysskrishna/video-extensions/blob/main/CONTRIBUTING.md) for details on our code of conduct, development setup, and the process for submitting pull requests.
|
|
119
|
+
|
|
120
|
+
|
|
121
|
+
## Support
|
|
122
|
+
|
|
123
|
+
If you find this library helpful:
|
|
124
|
+
|
|
125
|
+
- ⭐ Star the repository
|
|
126
|
+
- 🐛 Report issues
|
|
127
|
+
- 🔀 Submit pull requests
|
|
128
|
+
- 💝 [Sponsor on GitHub](https://github.com/sponsors/ysskrishna)
|
|
129
|
+
|
|
130
|
+
## Credits
|
|
131
|
+
|
|
132
|
+
This package is a Python port of the [video-extensions](https://github.com/sindresorhus/video-extensions) npm package by [Sindre Sorhus](https://github.com/sindresorhus).
|
|
133
|
+
|
|
134
|
+
|
|
135
|
+
## License
|
|
136
|
+
|
|
137
|
+
MIT © [Y. Siva Sai Krishna](https://github.com/ysskrishna) - see [LICENSE](https://github.com/ysskrishna/video-extensions/blob/main/LICENSE) for details.
|
|
138
|
+
|
|
139
|
+
---
|
|
140
|
+
|
|
141
|
+
<p align="left">
|
|
142
|
+
<a href="https://github.com/ysskrishna">Author's GitHub</a> •
|
|
143
|
+
<a href="https://linkedin.com/in/ysskrishna">Author's LinkedIn</a> •
|
|
144
|
+
<a href="https://pypi.org/project/video-extensions/">Package on PyPI</a> •
|
|
145
|
+
<a href="https://github.com/ysskrishna/video-extensions">GitHub Repository</a> •
|
|
146
|
+
<a href="https://github.com/ysskrishna/video-extensions/issues">Report Issues</a> •
|
|
147
|
+
<a href="https://github.com/ysskrishna/video-extensions/blob/main/CHANGELOG.md">Changelog</a> •
|
|
148
|
+
<a href="https://github.com/ysskrishna/video-extensions/releases">Release History</a>
|
|
149
|
+
</p>
|
|
@@ -0,0 +1,120 @@
|
|
|
1
|
+
# Video Extensions
|
|
2
|
+
|
|
3
|
+
[](https://www.python.org/downloads/)
|
|
4
|
+
[](https://github.com/ysskrishna/video-extensions/blob/main/LICENSE)
|
|
5
|
+

|
|
6
|
+
[](https://pypi.org/project/video-extensions/)
|
|
7
|
+
[](https://pepy.tech/projects/video-extensions)
|
|
8
|
+
|
|
9
|
+
Check if a file or extension is a video type, and iterate over 36 known video file formats including mp4, mov, avi, mkv, and more. Python port of [video-extensions](https://github.com/sindresorhus/video-extensions) npm package.
|
|
10
|
+
|
|
11
|
+
## Features
|
|
12
|
+
|
|
13
|
+
- Immutable collection of 36 known video file extensions
|
|
14
|
+
- Fast membership checks using `frozenset`
|
|
15
|
+
- Case-insensitive and dot-aware checks
|
|
16
|
+
- Works for both extensions and full file paths
|
|
17
|
+
- Supports dotfiles (e.g., `.mov`)
|
|
18
|
+
- Zero dependencies, minimal overhead
|
|
19
|
+
|
|
20
|
+
## Installation
|
|
21
|
+
|
|
22
|
+
```bash
|
|
23
|
+
pip install video-extensions
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
Or using `uv`:
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uv add video-extensions
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
## Usage
|
|
33
|
+
|
|
34
|
+
### Check if an extension is a video type
|
|
35
|
+
|
|
36
|
+
```python
|
|
37
|
+
from video_extensions import is_video_extension
|
|
38
|
+
|
|
39
|
+
is_video_extension("mp4") # True
|
|
40
|
+
is_video_extension(".mov") # True (dot-aware)
|
|
41
|
+
is_video_extension("AVI") # True (case-insensitive)
|
|
42
|
+
is_video_extension("txt") # False
|
|
43
|
+
```
|
|
44
|
+
|
|
45
|
+
### Check if a file path has a video extension
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
from video_extensions import is_video_path
|
|
49
|
+
|
|
50
|
+
is_video_path("movie.mp4") # True
|
|
51
|
+
is_video_path("/path/to/video.MOV") # True (case-insensitive)
|
|
52
|
+
is_video_path("presentation.avi") # True
|
|
53
|
+
is_video_path("document.txt") # False
|
|
54
|
+
is_video_path(".mov") # True (dotfile support)
|
|
55
|
+
```
|
|
56
|
+
|
|
57
|
+
### Access the list of video extensions
|
|
58
|
+
|
|
59
|
+
```python
|
|
60
|
+
from video_extensions import VIDEO_EXTENSIONS, VIDEO_EXTENSIONS_LOWER
|
|
61
|
+
|
|
62
|
+
# VIDEO_EXTENSIONS is a frozenset of all known video extensions
|
|
63
|
+
print(len(VIDEO_EXTENSIONS)) # 36
|
|
64
|
+
"mp4" in VIDEO_EXTENSIONS # True
|
|
65
|
+
"txt" in VIDEO_EXTENSIONS # False
|
|
66
|
+
|
|
67
|
+
# VIDEO_EXTENSIONS_LOWER contains all extensions in lowercase
|
|
68
|
+
# Useful for case-insensitive lookups without calling .lower() repeatedly
|
|
69
|
+
"MP4" in VIDEO_EXTENSIONS_LOWER # True (case-insensitive)
|
|
70
|
+
|
|
71
|
+
# Iterate over all extensions
|
|
72
|
+
for ext in sorted(VIDEO_EXTENSIONS):
|
|
73
|
+
print(ext)
|
|
74
|
+
```
|
|
75
|
+
|
|
76
|
+
## Supported Extensions
|
|
77
|
+
|
|
78
|
+
The package includes support for 36 video file extensions:
|
|
79
|
+
|
|
80
|
+
- **Common formats**: mp4, mov, avi, mkv, webm, flv, wmv, mpg, mpeg
|
|
81
|
+
- **Streaming**: m3u8, m4v, m4p, ogv, ogg
|
|
82
|
+
- **Professional**: mxf, drc, aaf, roq
|
|
83
|
+
- **Legacy**: 3gp, 3g2, asf, vob, rm, rmvb, qt
|
|
84
|
+
- **Specialized**: avchd, m2v, mp2, mpe, mpv, mng, nsv, svi, yuv, wmv
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
## Contributing
|
|
88
|
+
|
|
89
|
+
Contributions are welcome! Please read our [Contributing Guide](https://github.com/ysskrishna/video-extensions/blob/main/CONTRIBUTING.md) for details on our code of conduct, development setup, and the process for submitting pull requests.
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
## Support
|
|
93
|
+
|
|
94
|
+
If you find this library helpful:
|
|
95
|
+
|
|
96
|
+
- ⭐ Star the repository
|
|
97
|
+
- 🐛 Report issues
|
|
98
|
+
- 🔀 Submit pull requests
|
|
99
|
+
- 💝 [Sponsor on GitHub](https://github.com/sponsors/ysskrishna)
|
|
100
|
+
|
|
101
|
+
## Credits
|
|
102
|
+
|
|
103
|
+
This package is a Python port of the [video-extensions](https://github.com/sindresorhus/video-extensions) npm package by [Sindre Sorhus](https://github.com/sindresorhus).
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
## License
|
|
107
|
+
|
|
108
|
+
MIT © [Y. Siva Sai Krishna](https://github.com/ysskrishna) - see [LICENSE](https://github.com/ysskrishna/video-extensions/blob/main/LICENSE) for details.
|
|
109
|
+
|
|
110
|
+
---
|
|
111
|
+
|
|
112
|
+
<p align="left">
|
|
113
|
+
<a href="https://github.com/ysskrishna">Author's GitHub</a> •
|
|
114
|
+
<a href="https://linkedin.com/in/ysskrishna">Author's LinkedIn</a> •
|
|
115
|
+
<a href="https://pypi.org/project/video-extensions/">Package on PyPI</a> •
|
|
116
|
+
<a href="https://github.com/ysskrishna/video-extensions">GitHub Repository</a> •
|
|
117
|
+
<a href="https://github.com/ysskrishna/video-extensions/issues">Report Issues</a> •
|
|
118
|
+
<a href="https://github.com/ysskrishna/video-extensions/blob/main/CHANGELOG.md">Changelog</a> •
|
|
119
|
+
<a href="https://github.com/ysskrishna/video-extensions/releases">Release History</a>
|
|
120
|
+
</p>
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
[project]
|
|
2
|
+
name = "video-extensions"
|
|
3
|
+
version = "1.0.0"
|
|
4
|
+
description = "Check if a file or extension is a video type, and iterate over 36 known video file formats including mp4, mov, avi, mkv, and more. Python port of video-extensions npm package."
|
|
5
|
+
readme = "README.md"
|
|
6
|
+
requires-python = ">=3.8"
|
|
7
|
+
authors = [
|
|
8
|
+
{name = "ysskrishna", email = "sivasaikrishnassk@gmail.com"}
|
|
9
|
+
]
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
classifiers = [
|
|
12
|
+
"Programming Language :: Python :: 3",
|
|
13
|
+
"Programming Language :: Python :: 3.8",
|
|
14
|
+
"Programming Language :: Python :: 3.9",
|
|
15
|
+
"Programming Language :: Python :: 3.10",
|
|
16
|
+
"Programming Language :: Python :: 3.11",
|
|
17
|
+
"Programming Language :: Python :: 3.12",
|
|
18
|
+
"License :: OSI Approved :: MIT License",
|
|
19
|
+
"Operating System :: OS Independent",
|
|
20
|
+
"Development Status :: 5 - Production/Stable",
|
|
21
|
+
"Intended Audience :: Developers",
|
|
22
|
+
"Topic :: Software Development :: Libraries :: Python Modules",
|
|
23
|
+
"Topic :: Utilities",
|
|
24
|
+
"Typing :: Typed"
|
|
25
|
+
]
|
|
26
|
+
keywords = [
|
|
27
|
+
"video",
|
|
28
|
+
"extensions",
|
|
29
|
+
"extension",
|
|
30
|
+
"file",
|
|
31
|
+
"file-extensions",
|
|
32
|
+
"video-files",
|
|
33
|
+
"file-type",
|
|
34
|
+
"mime-type",
|
|
35
|
+
"file-detection",
|
|
36
|
+
"video-detection",
|
|
37
|
+
"file-utils",
|
|
38
|
+
"utilities",
|
|
39
|
+
"utils",
|
|
40
|
+
"mit license",
|
|
41
|
+
"ysskrishna"
|
|
42
|
+
]
|
|
43
|
+
dependencies = []
|
|
44
|
+
|
|
45
|
+
[dependency-groups]
|
|
46
|
+
dev = [
|
|
47
|
+
"pytest>=8.3.5",
|
|
48
|
+
]
|
|
49
|
+
|
|
50
|
+
[project.urls]
|
|
51
|
+
Homepage = "https://github.com/ysskrishna/video-extensions"
|
|
52
|
+
Repository = "https://github.com/ysskrishna/video-extensions.git"
|
|
53
|
+
Issues = "https://github.com/ysskrishna/video-extensions/issues"
|
|
54
|
+
Changelog = "https://github.com/ysskrishna/video-extensions/blob/main/CHANGELOG.md"
|
|
55
|
+
Discussions = "https://github.com/ysskrishna/video-extensions/discussions"
|
|
56
|
+
|
|
57
|
+
[build-system]
|
|
58
|
+
requires = ["hatchling"]
|
|
59
|
+
build-backend = "hatchling.build"
|
|
60
|
+
|
|
61
|
+
[tool.hatch.build.targets.wheel]
|
|
62
|
+
packages = ["video_extensions"]
|
|
63
|
+
|
|
File without changes
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
# Video extensions used for tests
|
|
2
|
+
VIDEO_EXAMPLES = ["mp4", "mov", "avi", "mkv", "webm", "flv", "wmv", "mpg", "mpeg"]
|
|
3
|
+
NON_VIDEO_EXAMPLES = ["txt", "md", "py", "js", "html", "css", "json", "xml"]
|
|
4
|
+
|
|
5
|
+
# Paths for testing is_video_path
|
|
6
|
+
VIDEO_PATHS = [
|
|
7
|
+
"movie.mp4",
|
|
8
|
+
"video.mov",
|
|
9
|
+
"film.avi",
|
|
10
|
+
"recording.mkv",
|
|
11
|
+
"clip.webm",
|
|
12
|
+
"stream.flv",
|
|
13
|
+
"presentation.wmv",
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
NON_VIDEO_PATHS = [
|
|
17
|
+
"readme.txt",
|
|
18
|
+
"script.py",
|
|
19
|
+
"style.css",
|
|
20
|
+
"index.html",
|
|
21
|
+
"data.json",
|
|
22
|
+
"config.xml",
|
|
23
|
+
]
|
|
24
|
+
|
|
25
|
+
HIDDEN_VIDEO_PATHS = [".hidden.mp4", ".config.mov"]
|
|
26
|
+
HIDDEN_NON_VIDEO_PATHS = [".gitignore"]
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from video_extensions import VIDEO_EXTENSIONS
|
|
3
|
+
from ._data import VIDEO_EXAMPLES
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
def test_video_extensions_type_and_content():
|
|
7
|
+
"""Check VIDEO_EXTENSIONS is a non-empty frozenset"""
|
|
8
|
+
assert isinstance(VIDEO_EXTENSIONS, frozenset)
|
|
9
|
+
assert len(VIDEO_EXTENSIONS) > 0
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.parametrize("ext", VIDEO_EXAMPLES)
|
|
13
|
+
def test_common_video_extensions_present(ext):
|
|
14
|
+
"""Check that common video extensions are present in VIDEO_EXTENSIONS"""
|
|
15
|
+
assert ext in VIDEO_EXTENSIONS
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from video_extensions import VIDEO_EXTENSIONS, is_video_extension, is_video_path
|
|
3
|
+
from ._data import VIDEO_EXAMPLES, VIDEO_PATHS
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize("ext,path,expected", [
|
|
7
|
+
("mp4", "file.mp4", True),
|
|
8
|
+
("mov", "video.mov", True),
|
|
9
|
+
("txt", "readme.txt", False),
|
|
10
|
+
("avi", "movie.avi", True),
|
|
11
|
+
("py", "script.py", False),
|
|
12
|
+
])
|
|
13
|
+
def test_consistency_between_functions(ext, path, expected):
|
|
14
|
+
"""Both functions return consistent results"""
|
|
15
|
+
assert is_video_extension(ext) == expected
|
|
16
|
+
assert is_video_path(path) == expected
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
def test_all_extensions_in_set():
|
|
20
|
+
"""Ensure all extensions in VIDEO_EXTENSIONS are recognized"""
|
|
21
|
+
for ext in VIDEO_EXTENSIONS:
|
|
22
|
+
assert is_video_extension(ext) is True
|
|
23
|
+
assert is_video_path(f"file.{ext}") is True
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from video_extensions import is_video_extension
|
|
3
|
+
from ._data import VIDEO_EXAMPLES, NON_VIDEO_EXAMPLES
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize("ext", VIDEO_EXAMPLES)
|
|
7
|
+
def test_video_extensions_true(ext):
|
|
8
|
+
"""Known video extensions should return True"""
|
|
9
|
+
assert is_video_extension(ext)
|
|
10
|
+
assert is_video_extension(f".{ext}")
|
|
11
|
+
assert is_video_extension(ext.upper())
|
|
12
|
+
assert is_video_extension(ext.title())
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
@pytest.mark.parametrize("ext", NON_VIDEO_EXAMPLES)
|
|
16
|
+
def test_non_video_extensions_false(ext):
|
|
17
|
+
"""Non-video extensions should return False"""
|
|
18
|
+
assert not is_video_extension(ext)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@pytest.mark.parametrize("ext", ["", ".", "unknown", "xyz"])
|
|
22
|
+
def test_edge_cases_false(ext):
|
|
23
|
+
"""Edge cases should return False"""
|
|
24
|
+
assert not is_video_extension(ext)
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import pytest
|
|
2
|
+
from video_extensions import is_video_path
|
|
3
|
+
from ._data import VIDEO_PATHS, NON_VIDEO_PATHS, HIDDEN_VIDEO_PATHS, HIDDEN_NON_VIDEO_PATHS
|
|
4
|
+
|
|
5
|
+
|
|
6
|
+
@pytest.mark.parametrize("path", VIDEO_PATHS + HIDDEN_VIDEO_PATHS)
|
|
7
|
+
def test_video_paths_true(path):
|
|
8
|
+
"""Paths with known video extensions should return True"""
|
|
9
|
+
assert is_video_path(path)
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
@pytest.mark.parametrize("path", NON_VIDEO_PATHS + HIDDEN_NON_VIDEO_PATHS)
|
|
13
|
+
def test_non_video_paths_false(path):
|
|
14
|
+
"""Paths without known video extensions should return False"""
|
|
15
|
+
assert not is_video_path(path)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
@pytest.mark.parametrize("path", ["", ".", "..", "file", "path/to/file", "file.name.txt"])
|
|
19
|
+
def test_paths_without_extension_false(path):
|
|
20
|
+
"""Paths without extensions or with non-video extensions should return False"""
|
|
21
|
+
assert not is_video_path(path)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
@pytest.mark.parametrize(
|
|
25
|
+
"path,expected",
|
|
26
|
+
[
|
|
27
|
+
("file.backup.mp4", True),
|
|
28
|
+
("movie.old.avi", True),
|
|
29
|
+
("file.name.txt", False),
|
|
30
|
+
("C:\\Users\\file.mov", True),
|
|
31
|
+
("/path/to/document.txt", False),
|
|
32
|
+
("VIDEO.MP4", True),
|
|
33
|
+
("Movie.MOV", True),
|
|
34
|
+
("Film.AVI", True),
|
|
35
|
+
("file.TXT", False),
|
|
36
|
+
("/path/to/video.mp4", True),
|
|
37
|
+
("folder/subfolder/file.mkv", True),
|
|
38
|
+
("file.", False),
|
|
39
|
+
]
|
|
40
|
+
)
|
|
41
|
+
def test_paths_various(path, expected):
|
|
42
|
+
"""Edge cases: multiple dots, OS paths, case insensitivity, directories"""
|
|
43
|
+
assert is_video_path(path) == expected
|
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
version = 1
|
|
2
|
+
revision = 3
|
|
3
|
+
requires-python = ">=3.8"
|
|
4
|
+
resolution-markers = [
|
|
5
|
+
"python_full_version >= '3.10'",
|
|
6
|
+
"python_full_version == '3.9.*'",
|
|
7
|
+
"python_full_version < '3.9'",
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
[[package]]
|
|
11
|
+
name = "colorama"
|
|
12
|
+
version = "0.4.6"
|
|
13
|
+
source = { registry = "https://pypi.org/simple" }
|
|
14
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d8/53/6f443c9a4a8358a93a6792e2acffb9d9d5cb0a5cfd8802644b7b1c9a02e4/colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44", size = 27697, upload-time = "2022-10-25T02:36:22.414Z" }
|
|
15
|
+
wheels = [
|
|
16
|
+
{ url = "https://files.pythonhosted.org/packages/d1/d6/3965ed04c63042e047cb6a3e6ed1a63a35087b6a609aa3a15ed8ac56c221/colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6", size = 25335, upload-time = "2022-10-25T02:36:20.889Z" },
|
|
17
|
+
]
|
|
18
|
+
|
|
19
|
+
[[package]]
|
|
20
|
+
name = "exceptiongroup"
|
|
21
|
+
version = "1.3.1"
|
|
22
|
+
source = { registry = "https://pypi.org/simple" }
|
|
23
|
+
dependencies = [
|
|
24
|
+
{ name = "typing-extensions", version = "4.13.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
25
|
+
{ name = "typing-extensions", version = "4.15.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.9' and python_full_version < '3.13'" },
|
|
26
|
+
]
|
|
27
|
+
sdist = { url = "https://files.pythonhosted.org/packages/50/79/66800aadf48771f6b62f7eb014e352e5d06856655206165d775e675a02c9/exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219", size = 30371, upload-time = "2025-11-21T23:01:54.787Z" }
|
|
28
|
+
wheels = [
|
|
29
|
+
{ url = "https://files.pythonhosted.org/packages/8a/0e/97c33bf5009bdbac74fd2beace167cab3f978feb69cc36f1ef79360d6c4e/exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598", size = 16740, upload-time = "2025-11-21T23:01:53.443Z" },
|
|
30
|
+
]
|
|
31
|
+
|
|
32
|
+
[[package]]
|
|
33
|
+
name = "iniconfig"
|
|
34
|
+
version = "2.1.0"
|
|
35
|
+
source = { registry = "https://pypi.org/simple" }
|
|
36
|
+
resolution-markers = [
|
|
37
|
+
"python_full_version == '3.9.*'",
|
|
38
|
+
"python_full_version < '3.9'",
|
|
39
|
+
]
|
|
40
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f2/97/ebf4da567aa6827c909642694d71c9fcf53e5b504f2d96afea02718862f3/iniconfig-2.1.0.tar.gz", hash = "sha256:3abbd2e30b36733fee78f9c7f7308f2d0050e88f0087fd25c2645f63c773e1c7", size = 4793, upload-time = "2025-03-19T20:09:59.721Z" }
|
|
41
|
+
wheels = [
|
|
42
|
+
{ url = "https://files.pythonhosted.org/packages/2c/e1/e6716421ea10d38022b952c159d5161ca1193197fb744506875fbb87ea7b/iniconfig-2.1.0-py3-none-any.whl", hash = "sha256:9deba5723312380e77435581c6bf4935c94cbfab9b1ed33ef8d238ea168eb760", size = 6050, upload-time = "2025-03-19T20:10:01.071Z" },
|
|
43
|
+
]
|
|
44
|
+
|
|
45
|
+
[[package]]
|
|
46
|
+
name = "iniconfig"
|
|
47
|
+
version = "2.3.0"
|
|
48
|
+
source = { registry = "https://pypi.org/simple" }
|
|
49
|
+
resolution-markers = [
|
|
50
|
+
"python_full_version >= '3.10'",
|
|
51
|
+
]
|
|
52
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/34/14ca021ce8e5dfedc35312d08ba8bf51fdd999c576889fc2c24cb97f4f10/iniconfig-2.3.0.tar.gz", hash = "sha256:c76315c77db068650d49c5b56314774a7804df16fee4402c1f19d6d15d8c4730", size = 20503, upload-time = "2025-10-18T21:55:43.219Z" }
|
|
53
|
+
wheels = [
|
|
54
|
+
{ url = "https://files.pythonhosted.org/packages/cb/b1/3846dd7f199d53cb17f49cba7e651e9ce294d8497c8c150530ed11865bb8/iniconfig-2.3.0-py3-none-any.whl", hash = "sha256:f631c04d2c48c52b84d0d0549c99ff3859c98df65b3101406327ecc7d53fbf12", size = 7484, upload-time = "2025-10-18T21:55:41.639Z" },
|
|
55
|
+
]
|
|
56
|
+
|
|
57
|
+
[[package]]
|
|
58
|
+
name = "packaging"
|
|
59
|
+
version = "26.0"
|
|
60
|
+
source = { registry = "https://pypi.org/simple" }
|
|
61
|
+
sdist = { url = "https://files.pythonhosted.org/packages/65/ee/299d360cdc32edc7d2cf530f3accf79c4fca01e96ffc950d8a52213bd8e4/packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4", size = 143416, upload-time = "2026-01-21T20:50:39.064Z" }
|
|
62
|
+
wheels = [
|
|
63
|
+
{ url = "https://files.pythonhosted.org/packages/b7/b9/c538f279a4e237a006a2c98387d081e9eb060d203d8ed34467cc0f0b9b53/packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529", size = 74366, upload-time = "2026-01-21T20:50:37.788Z" },
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
[[package]]
|
|
67
|
+
name = "pluggy"
|
|
68
|
+
version = "1.5.0"
|
|
69
|
+
source = { registry = "https://pypi.org/simple" }
|
|
70
|
+
resolution-markers = [
|
|
71
|
+
"python_full_version < '3.9'",
|
|
72
|
+
]
|
|
73
|
+
sdist = { url = "https://files.pythonhosted.org/packages/96/2d/02d4312c973c6050a18b314a5ad0b3210edb65a906f868e31c111dede4a6/pluggy-1.5.0.tar.gz", hash = "sha256:2cffa88e94fdc978c4c574f15f9e59b7f4201d439195c3715ca9e2486f1d0cf1", size = 67955, upload-time = "2024-04-20T21:34:42.531Z" }
|
|
74
|
+
wheels = [
|
|
75
|
+
{ url = "https://files.pythonhosted.org/packages/88/5f/e351af9a41f866ac3f1fac4ca0613908d9a41741cfcf2228f4ad853b697d/pluggy-1.5.0-py3-none-any.whl", hash = "sha256:44e1ad92c8ca002de6377e165f3e0f1be63266ab4d554740532335b9d75ea669", size = 20556, upload-time = "2024-04-20T21:34:40.434Z" },
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
[[package]]
|
|
79
|
+
name = "pluggy"
|
|
80
|
+
version = "1.6.0"
|
|
81
|
+
source = { registry = "https://pypi.org/simple" }
|
|
82
|
+
resolution-markers = [
|
|
83
|
+
"python_full_version >= '3.10'",
|
|
84
|
+
"python_full_version == '3.9.*'",
|
|
85
|
+
]
|
|
86
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f9/e2/3e91f31a7d2b083fe6ef3fa267035b518369d9511ffab804f839851d2779/pluggy-1.6.0.tar.gz", hash = "sha256:7dcc130b76258d33b90f61b658791dede3486c3e6bfb003ee5c9bfb396dd22f3", size = 69412, upload-time = "2025-05-15T12:30:07.975Z" }
|
|
87
|
+
wheels = [
|
|
88
|
+
{ url = "https://files.pythonhosted.org/packages/54/20/4d324d65cc6d9205fabedc306948156824eb9f0ee1633355a8f7ec5c66bf/pluggy-1.6.0-py3-none-any.whl", hash = "sha256:e920276dd6813095e9377c0bc5566d94c932c33b27a3e3945d8389c374dd4746", size = 20538, upload-time = "2025-05-15T12:30:06.134Z" },
|
|
89
|
+
]
|
|
90
|
+
|
|
91
|
+
[[package]]
|
|
92
|
+
name = "pygments"
|
|
93
|
+
version = "2.19.2"
|
|
94
|
+
source = { registry = "https://pypi.org/simple" }
|
|
95
|
+
sdist = { url = "https://files.pythonhosted.org/packages/b0/77/a5b8c569bf593b0140bde72ea885a803b82086995367bf2037de0159d924/pygments-2.19.2.tar.gz", hash = "sha256:636cb2477cec7f8952536970bc533bc43743542f70392ae026374600add5b887", size = 4968631, upload-time = "2025-06-21T13:39:12.283Z" }
|
|
96
|
+
wheels = [
|
|
97
|
+
{ url = "https://files.pythonhosted.org/packages/c7/21/705964c7812476f378728bdf590ca4b771ec72385c533964653c68e86bdc/pygments-2.19.2-py3-none-any.whl", hash = "sha256:86540386c03d588bb81d44bc3928634ff26449851e99741617ecb9037ee5ec0b", size = 1225217, upload-time = "2025-06-21T13:39:07.939Z" },
|
|
98
|
+
]
|
|
99
|
+
|
|
100
|
+
[[package]]
|
|
101
|
+
name = "pytest"
|
|
102
|
+
version = "8.3.5"
|
|
103
|
+
source = { registry = "https://pypi.org/simple" }
|
|
104
|
+
resolution-markers = [
|
|
105
|
+
"python_full_version < '3.9'",
|
|
106
|
+
]
|
|
107
|
+
dependencies = [
|
|
108
|
+
{ name = "colorama", marker = "python_full_version < '3.9' and sys_platform == 'win32'" },
|
|
109
|
+
{ name = "exceptiongroup", marker = "python_full_version < '3.9'" },
|
|
110
|
+
{ name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
111
|
+
{ name = "packaging", marker = "python_full_version < '3.9'" },
|
|
112
|
+
{ name = "pluggy", version = "1.5.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
113
|
+
{ name = "tomli", marker = "python_full_version < '3.9'" },
|
|
114
|
+
]
|
|
115
|
+
sdist = { url = "https://files.pythonhosted.org/packages/ae/3c/c9d525a414d506893f0cd8a8d0de7706446213181570cdbd766691164e40/pytest-8.3.5.tar.gz", hash = "sha256:f4efe70cc14e511565ac476b57c279e12a855b11f48f212af1080ef2263d3845", size = 1450891, upload-time = "2025-03-02T12:54:54.503Z" }
|
|
116
|
+
wheels = [
|
|
117
|
+
{ url = "https://files.pythonhosted.org/packages/30/3d/64ad57c803f1fa1e963a7946b6e0fea4a70df53c1a7fed304586539c2bac/pytest-8.3.5-py3-none-any.whl", hash = "sha256:c69214aa47deac29fad6c2a4f590b9c4a9fdb16a403176fe154b79c0b4d4d820", size = 343634, upload-time = "2025-03-02T12:54:52.069Z" },
|
|
118
|
+
]
|
|
119
|
+
|
|
120
|
+
[[package]]
|
|
121
|
+
name = "pytest"
|
|
122
|
+
version = "8.4.2"
|
|
123
|
+
source = { registry = "https://pypi.org/simple" }
|
|
124
|
+
resolution-markers = [
|
|
125
|
+
"python_full_version == '3.9.*'",
|
|
126
|
+
]
|
|
127
|
+
dependencies = [
|
|
128
|
+
{ name = "colorama", marker = "python_full_version == '3.9.*' and sys_platform == 'win32'" },
|
|
129
|
+
{ name = "exceptiongroup", marker = "python_full_version == '3.9.*'" },
|
|
130
|
+
{ name = "iniconfig", version = "2.1.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" },
|
|
131
|
+
{ name = "packaging", marker = "python_full_version == '3.9.*'" },
|
|
132
|
+
{ name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" },
|
|
133
|
+
{ name = "pygments", marker = "python_full_version == '3.9.*'" },
|
|
134
|
+
{ name = "tomli", marker = "python_full_version == '3.9.*'" },
|
|
135
|
+
]
|
|
136
|
+
sdist = { url = "https://files.pythonhosted.org/packages/a3/5c/00a0e072241553e1a7496d638deababa67c5058571567b92a7eaa258397c/pytest-8.4.2.tar.gz", hash = "sha256:86c0d0b93306b961d58d62a4db4879f27fe25513d4b969df351abdddb3c30e01", size = 1519618, upload-time = "2025-09-04T14:34:22.711Z" }
|
|
137
|
+
wheels = [
|
|
138
|
+
{ url = "https://files.pythonhosted.org/packages/a8/a4/20da314d277121d6534b3a980b29035dcd51e6744bd79075a6ce8fa4eb8d/pytest-8.4.2-py3-none-any.whl", hash = "sha256:872f880de3fc3a5bdc88a11b39c9710c3497a547cfa9320bc3c5e62fbf272e79", size = 365750, upload-time = "2025-09-04T14:34:20.226Z" },
|
|
139
|
+
]
|
|
140
|
+
|
|
141
|
+
[[package]]
|
|
142
|
+
name = "pytest"
|
|
143
|
+
version = "9.0.2"
|
|
144
|
+
source = { registry = "https://pypi.org/simple" }
|
|
145
|
+
resolution-markers = [
|
|
146
|
+
"python_full_version >= '3.10'",
|
|
147
|
+
]
|
|
148
|
+
dependencies = [
|
|
149
|
+
{ name = "colorama", marker = "python_full_version >= '3.10' and sys_platform == 'win32'" },
|
|
150
|
+
{ name = "exceptiongroup", marker = "python_full_version == '3.10.*'" },
|
|
151
|
+
{ name = "iniconfig", version = "2.3.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
152
|
+
{ name = "packaging", marker = "python_full_version >= '3.10'" },
|
|
153
|
+
{ name = "pluggy", version = "1.6.0", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
154
|
+
{ name = "pygments", marker = "python_full_version >= '3.10'" },
|
|
155
|
+
{ name = "tomli", marker = "python_full_version == '3.10.*'" },
|
|
156
|
+
]
|
|
157
|
+
sdist = { url = "https://files.pythonhosted.org/packages/d1/db/7ef3487e0fb0049ddb5ce41d3a49c235bf9ad299b6a25d5780a89f19230f/pytest-9.0.2.tar.gz", hash = "sha256:75186651a92bd89611d1d9fc20f0b4345fd827c41ccd5c299a868a05d70edf11", size = 1568901, upload-time = "2025-12-06T21:30:51.014Z" }
|
|
158
|
+
wheels = [
|
|
159
|
+
{ url = "https://files.pythonhosted.org/packages/3b/ab/b3226f0bd7cdcf710fbede2b3548584366da3b19b5021e74f5bde2a8fa3f/pytest-9.0.2-py3-none-any.whl", hash = "sha256:711ffd45bf766d5264d487b917733b453d917afd2b0ad65223959f59089f875b", size = 374801, upload-time = "2025-12-06T21:30:49.154Z" },
|
|
160
|
+
]
|
|
161
|
+
|
|
162
|
+
[[package]]
|
|
163
|
+
name = "tomli"
|
|
164
|
+
version = "2.4.0"
|
|
165
|
+
source = { registry = "https://pypi.org/simple" }
|
|
166
|
+
sdist = { url = "https://files.pythonhosted.org/packages/82/30/31573e9457673ab10aa432461bee537ce6cef177667deca369efb79df071/tomli-2.4.0.tar.gz", hash = "sha256:aa89c3f6c277dd275d8e243ad24f3b5e701491a860d5121f2cdd399fbb31fc9c", size = 17477, upload-time = "2026-01-11T11:22:38.165Z" }
|
|
167
|
+
wheels = [
|
|
168
|
+
{ url = "https://files.pythonhosted.org/packages/3c/d9/3dc2289e1f3b32eb19b9785b6a006b28ee99acb37d1d47f78d4c10e28bf8/tomli-2.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b5ef256a3fd497d4973c11bf142e9ed78b150d36f5773f1ca6088c230ffc5867", size = 153663, upload-time = "2026-01-11T11:21:45.27Z" },
|
|
169
|
+
{ url = "https://files.pythonhosted.org/packages/51/32/ef9f6845e6b9ca392cd3f64f9ec185cc6f09f0a2df3db08cbe8809d1d435/tomli-2.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:5572e41282d5268eb09a697c89a7bee84fae66511f87533a6f88bd2f7b652da9", size = 148469, upload-time = "2026-01-11T11:21:46.873Z" },
|
|
170
|
+
{ url = "https://files.pythonhosted.org/packages/d6/c2/506e44cce89a8b1b1e047d64bd495c22c9f71f21e05f380f1a950dd9c217/tomli-2.4.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:551e321c6ba03b55676970b47cb1b73f14a0a4dce6a3e1a9458fd6d921d72e95", size = 236039, upload-time = "2026-01-11T11:21:48.503Z" },
|
|
171
|
+
{ url = "https://files.pythonhosted.org/packages/b3/40/e1b65986dbc861b7e986e8ec394598187fa8aee85b1650b01dd925ca0be8/tomli-2.4.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5e3f639a7a8f10069d0e15408c0b96a2a828cfdec6fca05296ebcdcc28ca7c76", size = 243007, upload-time = "2026-01-11T11:21:49.456Z" },
|
|
172
|
+
{ url = "https://files.pythonhosted.org/packages/9c/6f/6e39ce66b58a5b7ae572a0f4352ff40c71e8573633deda43f6a379d56b3e/tomli-2.4.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:1b168f2731796b045128c45982d3a4874057626da0e2ef1fdd722848b741361d", size = 240875, upload-time = "2026-01-11T11:21:50.755Z" },
|
|
173
|
+
{ url = "https://files.pythonhosted.org/packages/aa/ad/cb089cb190487caa80204d503c7fd0f4d443f90b95cf4ef5cf5aa0f439b0/tomli-2.4.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:133e93646ec4300d651839d382d63edff11d8978be23da4cc106f5a18b7d0576", size = 246271, upload-time = "2026-01-11T11:21:51.81Z" },
|
|
174
|
+
{ url = "https://files.pythonhosted.org/packages/0b/63/69125220e47fd7a3a27fd0de0c6398c89432fec41bc739823bcc66506af6/tomli-2.4.0-cp311-cp311-win32.whl", hash = "sha256:b6c78bdf37764092d369722d9946cb65b8767bfa4110f902a1b2542d8d173c8a", size = 96770, upload-time = "2026-01-11T11:21:52.647Z" },
|
|
175
|
+
{ url = "https://files.pythonhosted.org/packages/1e/0d/a22bb6c83f83386b0008425a6cd1fa1c14b5f3dd4bad05e98cf3dbbf4a64/tomli-2.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:d3d1654e11d724760cdb37a3d7691f0be9db5fbdaef59c9f532aabf87006dbaa", size = 107626, upload-time = "2026-01-11T11:21:53.459Z" },
|
|
176
|
+
{ url = "https://files.pythonhosted.org/packages/2f/6d/77be674a3485e75cacbf2ddba2b146911477bd887dda9d8c9dfb2f15e871/tomli-2.4.0-cp311-cp311-win_arm64.whl", hash = "sha256:cae9c19ed12d4e8f3ebf46d1a75090e4c0dc16271c5bce1c833ac168f08fb614", size = 94842, upload-time = "2026-01-11T11:21:54.831Z" },
|
|
177
|
+
{ url = "https://files.pythonhosted.org/packages/3c/43/7389a1869f2f26dba52404e1ef13b4784b6b37dac93bac53457e3ff24ca3/tomli-2.4.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:920b1de295e72887bafa3ad9f7a792f811847d57ea6b1215154030cf131f16b1", size = 154894, upload-time = "2026-01-11T11:21:56.07Z" },
|
|
178
|
+
{ url = "https://files.pythonhosted.org/packages/e9/05/2f9bf110b5294132b2edf13fe6ca6ae456204f3d749f623307cbb7a946f2/tomli-2.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7d6d9a4aee98fac3eab4952ad1d73aee87359452d1c086b5ceb43ed02ddb16b8", size = 149053, upload-time = "2026-01-11T11:21:57.467Z" },
|
|
179
|
+
{ url = "https://files.pythonhosted.org/packages/e8/41/1eda3ca1abc6f6154a8db4d714a4d35c4ad90adc0bcf700657291593fbf3/tomli-2.4.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:36b9d05b51e65b254ea6c2585b59d2c4cb91c8a3d91d0ed0f17591a29aaea54a", size = 243481, upload-time = "2026-01-11T11:21:58.661Z" },
|
|
180
|
+
{ url = "https://files.pythonhosted.org/packages/d2/6d/02ff5ab6c8868b41e7d4b987ce2b5f6a51d3335a70aa144edd999e055a01/tomli-2.4.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1c8a885b370751837c029ef9bc014f27d80840e48bac415f3412e6593bbc18c1", size = 251720, upload-time = "2026-01-11T11:22:00.178Z" },
|
|
181
|
+
{ url = "https://files.pythonhosted.org/packages/7b/57/0405c59a909c45d5b6f146107c6d997825aa87568b042042f7a9c0afed34/tomli-2.4.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:8768715ffc41f0008abe25d808c20c3d990f42b6e2e58305d5da280ae7d1fa3b", size = 247014, upload-time = "2026-01-11T11:22:01.238Z" },
|
|
182
|
+
{ url = "https://files.pythonhosted.org/packages/2c/0e/2e37568edd944b4165735687cbaf2fe3648129e440c26d02223672ee0630/tomli-2.4.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:7b438885858efd5be02a9a133caf5812b8776ee0c969fea02c45e8e3f296ba51", size = 251820, upload-time = "2026-01-11T11:22:02.727Z" },
|
|
183
|
+
{ url = "https://files.pythonhosted.org/packages/5a/1c/ee3b707fdac82aeeb92d1a113f803cf6d0f37bdca0849cb489553e1f417a/tomli-2.4.0-cp312-cp312-win32.whl", hash = "sha256:0408e3de5ec77cc7f81960c362543cbbd91ef883e3138e81b729fc3eea5b9729", size = 97712, upload-time = "2026-01-11T11:22:03.777Z" },
|
|
184
|
+
{ url = "https://files.pythonhosted.org/packages/69/13/c07a9177d0b3bab7913299b9278845fc6eaaca14a02667c6be0b0a2270c8/tomli-2.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:685306e2cc7da35be4ee914fd34ab801a6acacb061b6a7abca922aaf9ad368da", size = 108296, upload-time = "2026-01-11T11:22:04.86Z" },
|
|
185
|
+
{ url = "https://files.pythonhosted.org/packages/18/27/e267a60bbeeee343bcc279bb9e8fbed0cbe224bc7b2a3dc2975f22809a09/tomli-2.4.0-cp312-cp312-win_arm64.whl", hash = "sha256:5aa48d7c2356055feef06a43611fc401a07337d5b006be13a30f6c58f869e3c3", size = 94553, upload-time = "2026-01-11T11:22:05.854Z" },
|
|
186
|
+
{ url = "https://files.pythonhosted.org/packages/34/91/7f65f9809f2936e1f4ce6268ae1903074563603b2a2bd969ebbda802744f/tomli-2.4.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:84d081fbc252d1b6a982e1870660e7330fb8f90f676f6e78b052ad4e64714bf0", size = 154915, upload-time = "2026-01-11T11:22:06.703Z" },
|
|
187
|
+
{ url = "https://files.pythonhosted.org/packages/20/aa/64dd73a5a849c2e8f216b755599c511badde80e91e9bc2271baa7b2cdbb1/tomli-2.4.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9a08144fa4cba33db5255f9b74f0b89888622109bd2776148f2597447f92a94e", size = 149038, upload-time = "2026-01-11T11:22:07.56Z" },
|
|
188
|
+
{ url = "https://files.pythonhosted.org/packages/9e/8a/6d38870bd3d52c8d1505ce054469a73f73a0fe62c0eaf5dddf61447e32fa/tomli-2.4.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c73add4bb52a206fd0c0723432db123c0c75c280cbd67174dd9d2db228ebb1b4", size = 242245, upload-time = "2026-01-11T11:22:08.344Z" },
|
|
189
|
+
{ url = "https://files.pythonhosted.org/packages/59/bb/8002fadefb64ab2669e5b977df3f5e444febea60e717e755b38bb7c41029/tomli-2.4.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1fb2945cbe303b1419e2706e711b7113da57b7db31ee378d08712d678a34e51e", size = 250335, upload-time = "2026-01-11T11:22:09.951Z" },
|
|
190
|
+
{ url = "https://files.pythonhosted.org/packages/a5/3d/4cdb6f791682b2ea916af2de96121b3cb1284d7c203d97d92d6003e91c8d/tomli-2.4.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:bbb1b10aa643d973366dc2cb1ad94f99c1726a02343d43cbc011edbfac579e7c", size = 245962, upload-time = "2026-01-11T11:22:11.27Z" },
|
|
191
|
+
{ url = "https://files.pythonhosted.org/packages/f2/4a/5f25789f9a460bd858ba9756ff52d0830d825b458e13f754952dd15fb7bb/tomli-2.4.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:4cbcb367d44a1f0c2be408758b43e1ffb5308abe0ea222897d6bfc8e8281ef2f", size = 250396, upload-time = "2026-01-11T11:22:12.325Z" },
|
|
192
|
+
{ url = "https://files.pythonhosted.org/packages/aa/2f/b73a36fea58dfa08e8b3a268750e6853a6aac2a349241a905ebd86f3047a/tomli-2.4.0-cp313-cp313-win32.whl", hash = "sha256:7d49c66a7d5e56ac959cb6fc583aff0651094ec071ba9ad43df785abc2320d86", size = 97530, upload-time = "2026-01-11T11:22:13.865Z" },
|
|
193
|
+
{ url = "https://files.pythonhosted.org/packages/3b/af/ca18c134b5d75de7e8dc551c5234eaba2e8e951f6b30139599b53de9c187/tomli-2.4.0-cp313-cp313-win_amd64.whl", hash = "sha256:3cf226acb51d8f1c394c1b310e0e0e61fecdd7adcb78d01e294ac297dd2e7f87", size = 108227, upload-time = "2026-01-11T11:22:15.224Z" },
|
|
194
|
+
{ url = "https://files.pythonhosted.org/packages/22/c3/b386b832f209fee8073c8138ec50f27b4460db2fdae9ffe022df89a57f9b/tomli-2.4.0-cp313-cp313-win_arm64.whl", hash = "sha256:d20b797a5c1ad80c516e41bc1fb0443ddb5006e9aaa7bda2d71978346aeb9132", size = 94748, upload-time = "2026-01-11T11:22:16.009Z" },
|
|
195
|
+
{ url = "https://files.pythonhosted.org/packages/f3/c4/84047a97eb1004418bc10bdbcfebda209fca6338002eba2dc27cc6d13563/tomli-2.4.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:26ab906a1eb794cd4e103691daa23d95c6919cc2fa9160000ac02370cc9dd3f6", size = 154725, upload-time = "2026-01-11T11:22:17.269Z" },
|
|
196
|
+
{ url = "https://files.pythonhosted.org/packages/a8/5d/d39038e646060b9d76274078cddf146ced86dc2b9e8bbf737ad5983609a0/tomli-2.4.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:20cedb4ee43278bc4f2fee6cb50daec836959aadaf948db5172e776dd3d993fc", size = 148901, upload-time = "2026-01-11T11:22:18.287Z" },
|
|
197
|
+
{ url = "https://files.pythonhosted.org/packages/73/e5/383be1724cb30f4ce44983d249645684a48c435e1cd4f8b5cded8a816d3c/tomli-2.4.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:39b0b5d1b6dd03684b3fb276407ebed7090bbec989fa55838c98560c01113b66", size = 243375, upload-time = "2026-01-11T11:22:19.154Z" },
|
|
198
|
+
{ url = "https://files.pythonhosted.org/packages/31/f0/bea80c17971c8d16d3cc109dc3585b0f2ce1036b5f4a8a183789023574f2/tomli-2.4.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a26d7ff68dfdb9f87a016ecfd1e1c2bacbe3108f4e0f8bcd2228ef9a766c787d", size = 250639, upload-time = "2026-01-11T11:22:20.168Z" },
|
|
199
|
+
{ url = "https://files.pythonhosted.org/packages/2c/8f/2853c36abbb7608e3f945d8a74e32ed3a74ee3a1f468f1ffc7d1cb3abba6/tomli-2.4.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:20ffd184fb1df76a66e34bd1b36b4a4641bd2b82954befa32fe8163e79f1a702", size = 246897, upload-time = "2026-01-11T11:22:21.544Z" },
|
|
200
|
+
{ url = "https://files.pythonhosted.org/packages/49/f0/6c05e3196ed5337b9fe7ea003e95fd3819a840b7a0f2bf5a408ef1dad8ed/tomli-2.4.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:75c2f8bbddf170e8effc98f5e9084a8751f8174ea6ccf4fca5398436e0320bc8", size = 254697, upload-time = "2026-01-11T11:22:23.058Z" },
|
|
201
|
+
{ url = "https://files.pythonhosted.org/packages/f3/f5/2922ef29c9f2951883525def7429967fc4d8208494e5ab524234f06b688b/tomli-2.4.0-cp314-cp314-win32.whl", hash = "sha256:31d556d079d72db7c584c0627ff3a24c5d3fb4f730221d3444f3efb1b2514776", size = 98567, upload-time = "2026-01-11T11:22:24.033Z" },
|
|
202
|
+
{ url = "https://files.pythonhosted.org/packages/7b/31/22b52e2e06dd2a5fdbc3ee73226d763b184ff21fc24e20316a44ccc4d96b/tomli-2.4.0-cp314-cp314-win_amd64.whl", hash = "sha256:43e685b9b2341681907759cf3a04e14d7104b3580f808cfde1dfdb60ada85475", size = 108556, upload-time = "2026-01-11T11:22:25.378Z" },
|
|
203
|
+
{ url = "https://files.pythonhosted.org/packages/48/3d/5058dff3255a3d01b705413f64f4306a141a8fd7a251e5a495e3f192a998/tomli-2.4.0-cp314-cp314-win_arm64.whl", hash = "sha256:3d895d56bd3f82ddd6faaff993c275efc2ff38e52322ea264122d72729dca2b2", size = 96014, upload-time = "2026-01-11T11:22:26.138Z" },
|
|
204
|
+
{ url = "https://files.pythonhosted.org/packages/b8/4e/75dab8586e268424202d3a1997ef6014919c941b50642a1682df43204c22/tomli-2.4.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:5b5807f3999fb66776dbce568cc9a828544244a8eb84b84b9bafc080c99597b9", size = 163339, upload-time = "2026-01-11T11:22:27.143Z" },
|
|
205
|
+
{ url = "https://files.pythonhosted.org/packages/06/e3/b904d9ab1016829a776d97f163f183a48be6a4deb87304d1e0116a349519/tomli-2.4.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:c084ad935abe686bd9c898e62a02a19abfc9760b5a79bc29644463eaf2840cb0", size = 159490, upload-time = "2026-01-11T11:22:28.399Z" },
|
|
206
|
+
{ url = "https://files.pythonhosted.org/packages/e3/5a/fc3622c8b1ad823e8ea98a35e3c632ee316d48f66f80f9708ceb4f2a0322/tomli-2.4.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f2e3955efea4d1cfbcb87bc321e00dc08d2bcb737fd1d5e398af111d86db5df", size = 269398, upload-time = "2026-01-11T11:22:29.345Z" },
|
|
207
|
+
{ url = "https://files.pythonhosted.org/packages/fd/33/62bd6152c8bdd4c305ad9faca48f51d3acb2df1f8791b1477d46ff86e7f8/tomli-2.4.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e0fe8a0b8312acf3a88077a0802565cb09ee34107813bba1c7cd591fa6cfc8d", size = 276515, upload-time = "2026-01-11T11:22:30.327Z" },
|
|
208
|
+
{ url = "https://files.pythonhosted.org/packages/4b/ff/ae53619499f5235ee4211e62a8d7982ba9e439a0fb4f2f351a93d67c1dd2/tomli-2.4.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:413540dce94673591859c4c6f794dfeaa845e98bf35d72ed59636f869ef9f86f", size = 273806, upload-time = "2026-01-11T11:22:32.56Z" },
|
|
209
|
+
{ url = "https://files.pythonhosted.org/packages/47/71/cbca7787fa68d4d0a9f7072821980b39fbb1b6faeb5f5cf02f4a5559fa28/tomli-2.4.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0dc56fef0e2c1c470aeac5b6ca8cc7b640bb93e92d9803ddaf9ea03e198f5b0b", size = 281340, upload-time = "2026-01-11T11:22:33.505Z" },
|
|
210
|
+
{ url = "https://files.pythonhosted.org/packages/f5/00/d595c120963ad42474cf6ee7771ad0d0e8a49d0f01e29576ee9195d9ecdf/tomli-2.4.0-cp314-cp314t-win32.whl", hash = "sha256:d878f2a6707cc9d53a1be1414bbb419e629c3d6e67f69230217bb663e76b5087", size = 108106, upload-time = "2026-01-11T11:22:34.451Z" },
|
|
211
|
+
{ url = "https://files.pythonhosted.org/packages/de/69/9aa0c6a505c2f80e519b43764f8b4ba93b5a0bbd2d9a9de6e2b24271b9a5/tomli-2.4.0-cp314-cp314t-win_amd64.whl", hash = "sha256:2add28aacc7425117ff6364fe9e06a183bb0251b03f986df0e78e974047571fd", size = 120504, upload-time = "2026-01-11T11:22:35.764Z" },
|
|
212
|
+
{ url = "https://files.pythonhosted.org/packages/b3/9f/f1668c281c58cfae01482f7114a4b88d345e4c140386241a1a24dcc9e7bc/tomli-2.4.0-cp314-cp314t-win_arm64.whl", hash = "sha256:2b1e3b80e1d5e52e40e9b924ec43d81570f0e7d09d11081b797bc4692765a3d4", size = 99561, upload-time = "2026-01-11T11:22:36.624Z" },
|
|
213
|
+
{ url = "https://files.pythonhosted.org/packages/23/d1/136eb2cb77520a31e1f64cbae9d33ec6df0d78bdf4160398e86eec8a8754/tomli-2.4.0-py3-none-any.whl", hash = "sha256:1f776e7d669ebceb01dee46484485f43a4048746235e683bcdffacdf1fb4785a", size = 14477, upload-time = "2026-01-11T11:22:37.446Z" },
|
|
214
|
+
]
|
|
215
|
+
|
|
216
|
+
[[package]]
|
|
217
|
+
name = "typing-extensions"
|
|
218
|
+
version = "4.13.2"
|
|
219
|
+
source = { registry = "https://pypi.org/simple" }
|
|
220
|
+
resolution-markers = [
|
|
221
|
+
"python_full_version < '3.9'",
|
|
222
|
+
]
|
|
223
|
+
sdist = { url = "https://files.pythonhosted.org/packages/f6/37/23083fcd6e35492953e8d2aaaa68b860eb422b34627b13f2ce3eb6106061/typing_extensions-4.13.2.tar.gz", hash = "sha256:e6c81219bd689f51865d9e372991c540bda33a0379d5573cddb9a3a23f7caaef", size = 106967, upload-time = "2025-04-10T14:19:05.416Z" }
|
|
224
|
+
wheels = [
|
|
225
|
+
{ url = "https://files.pythonhosted.org/packages/8b/54/b1ae86c0973cc6f0210b53d508ca3641fb6d0c56823f288d108bc7ab3cc8/typing_extensions-4.13.2-py3-none-any.whl", hash = "sha256:a439e7c04b49fec3e5d3e2beaa21755cadbbdc391694e28ccdd36ca4a1408f8c", size = 45806, upload-time = "2025-04-10T14:19:03.967Z" },
|
|
226
|
+
]
|
|
227
|
+
|
|
228
|
+
[[package]]
|
|
229
|
+
name = "typing-extensions"
|
|
230
|
+
version = "4.15.0"
|
|
231
|
+
source = { registry = "https://pypi.org/simple" }
|
|
232
|
+
resolution-markers = [
|
|
233
|
+
"python_full_version >= '3.10'",
|
|
234
|
+
"python_full_version == '3.9.*'",
|
|
235
|
+
]
|
|
236
|
+
sdist = { url = "https://files.pythonhosted.org/packages/72/94/1a15dd82efb362ac84269196e94cf00f187f7ed21c242792a923cdb1c61f/typing_extensions-4.15.0.tar.gz", hash = "sha256:0cea48d173cc12fa28ecabc3b837ea3cf6f38c6d1136f85cbaaf598984861466", size = 109391, upload-time = "2025-08-25T13:49:26.313Z" }
|
|
237
|
+
wheels = [
|
|
238
|
+
{ url = "https://files.pythonhosted.org/packages/18/67/36e9267722cc04a6b9f15c7f3441c2363321a3ea07da7ae0c0707beb2a9c/typing_extensions-4.15.0-py3-none-any.whl", hash = "sha256:f0fa19c6845758ab08074a0cfa8b7aecb71c999ca73d62883bc25cc018c4e548", size = 44614, upload-time = "2025-08-25T13:49:24.86Z" },
|
|
239
|
+
]
|
|
240
|
+
|
|
241
|
+
[[package]]
|
|
242
|
+
name = "video-extensions"
|
|
243
|
+
version = "1.0.0"
|
|
244
|
+
source = { editable = "." }
|
|
245
|
+
|
|
246
|
+
[package.dev-dependencies]
|
|
247
|
+
dev = [
|
|
248
|
+
{ name = "pytest", version = "8.3.5", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version < '3.9'" },
|
|
249
|
+
{ name = "pytest", version = "8.4.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version == '3.9.*'" },
|
|
250
|
+
{ name = "pytest", version = "9.0.2", source = { registry = "https://pypi.org/simple" }, marker = "python_full_version >= '3.10'" },
|
|
251
|
+
]
|
|
252
|
+
|
|
253
|
+
[package.metadata]
|
|
254
|
+
|
|
255
|
+
[package.metadata.requires-dev]
|
|
256
|
+
dev = [{ name = "pytest", specifier = ">=8.3.5" }]
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import os.path
|
|
2
|
+
from video_extensions._data import VIDEO_EXTENSIONS, VIDEO_EXTENSIONS_LOWER
|
|
3
|
+
|
|
4
|
+
__all__ = ["VIDEO_EXTENSIONS", "VIDEO_EXTENSIONS_LOWER", "is_video_extension", "is_video_path"]
|
|
5
|
+
|
|
6
|
+
def is_video_extension(ext: str) -> bool:
|
|
7
|
+
"""
|
|
8
|
+
Return True if the given file extension is known to be a video type.
|
|
9
|
+
|
|
10
|
+
Examples:
|
|
11
|
+
>>> is_video_extension("mp4")
|
|
12
|
+
True
|
|
13
|
+
>>> is_video_extension(".txt")
|
|
14
|
+
False
|
|
15
|
+
"""
|
|
16
|
+
return ext.lower().lstrip(".") in VIDEO_EXTENSIONS_LOWER
|
|
17
|
+
|
|
18
|
+
def is_video_path(file_path: str) -> bool:
|
|
19
|
+
"""
|
|
20
|
+
Return True if the file path has a video file extension.
|
|
21
|
+
|
|
22
|
+
Examples:
|
|
23
|
+
>>> is_video_path("movie.mp4")
|
|
24
|
+
True
|
|
25
|
+
>>> is_video_path("document.txt")
|
|
26
|
+
False
|
|
27
|
+
>>> is_video_path("/path/to/video.MOV")
|
|
28
|
+
True
|
|
29
|
+
"""
|
|
30
|
+
basename = os.path.basename(file_path)
|
|
31
|
+
_, ext = os.path.splitext(file_path)
|
|
32
|
+
|
|
33
|
+
# Handle dotfiles (files starting with a dot that have no extension)
|
|
34
|
+
# e.g., .something where "something" is a video extension
|
|
35
|
+
if not ext and basename.startswith(".") and len(basename) > 1:
|
|
36
|
+
# Treat the entire filename (without leading dot) as the extension
|
|
37
|
+
ext = basename[1:]
|
|
38
|
+
else:
|
|
39
|
+
ext = ext.lstrip(".")
|
|
40
|
+
|
|
41
|
+
return ext.lower() in VIDEO_EXTENSIONS_LOWER
|
|
42
|
+
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
VIDEO_EXTENSIONS = frozenset((
|
|
2
|
+
"3g2",
|
|
3
|
+
"3gp",
|
|
4
|
+
"aaf",
|
|
5
|
+
"asf",
|
|
6
|
+
"avchd",
|
|
7
|
+
"avi",
|
|
8
|
+
"drc",
|
|
9
|
+
"flv",
|
|
10
|
+
"m2v",
|
|
11
|
+
"m3u8",
|
|
12
|
+
"m4p",
|
|
13
|
+
"m4v",
|
|
14
|
+
"mkv",
|
|
15
|
+
"mng",
|
|
16
|
+
"mov",
|
|
17
|
+
"mp2",
|
|
18
|
+
"mp4",
|
|
19
|
+
"mpe",
|
|
20
|
+
"mpeg",
|
|
21
|
+
"mpg",
|
|
22
|
+
"mpv",
|
|
23
|
+
"mxf",
|
|
24
|
+
"nsv",
|
|
25
|
+
"ogg",
|
|
26
|
+
"ogv",
|
|
27
|
+
"qt",
|
|
28
|
+
"rm",
|
|
29
|
+
"rmvb",
|
|
30
|
+
"roq",
|
|
31
|
+
"svi",
|
|
32
|
+
"vob",
|
|
33
|
+
"webm",
|
|
34
|
+
"wmv",
|
|
35
|
+
"yuv"
|
|
36
|
+
))
|
|
37
|
+
|
|
38
|
+
VIDEO_EXTENSIONS_LOWER = frozenset(ext.lower() for ext in VIDEO_EXTENSIONS)
|
|
File without changes
|