uDownloader 0.1.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.
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 uDownloader Contributors
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,4 @@
1
+ include README.md
2
+ include LICENSE
3
+ include requirements.txt
4
+ recursive-include youdownload *.py
@@ -0,0 +1,229 @@
1
+ Metadata-Version: 2.4
2
+ Name: uDownloader
3
+ Version: 0.1.0
4
+ Summary: Fast, async YouTube/Instagram/TikTok downloader with desktop GUI and CLI
5
+ Author: Developer
6
+ License: MIT
7
+ Project-URL: Homepage, https://github.com/yourusername/uDownloader
8
+ Project-URL: Documentation, https://github.com/yourusername/uDownloader#readme
9
+ Project-URL: Repository, https://github.com/yourusername/uDownloader.git
10
+ Project-URL: Issues, https://github.com/yourusername/uDownloader/issues
11
+ Keywords: youtube,instagram,downloader,video,audio,desktop
12
+ Classifier: Development Status :: 4 - Beta
13
+ Classifier: Environment :: X11 Applications :: Qt
14
+ Classifier: Intended Audience :: End Users/Desktop
15
+ Classifier: License :: OSI Approved :: MIT License
16
+ Classifier: Programming Language :: Python :: 3
17
+ Classifier: Programming Language :: Python :: 3.8
18
+ Classifier: Programming Language :: Python :: 3.9
19
+ Classifier: Programming Language :: Python :: 3.10
20
+ Classifier: Programming Language :: Python :: 3.11
21
+ Classifier: Programming Language :: Python :: 3.12
22
+ Classifier: Topic :: Multimedia :: Video
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.8
25
+ Description-Content-Type: text/markdown
26
+ License-File: LICENSE
27
+ Requires-Dist: yt-dlp>=2024.8.2
28
+ Requires-Dist: PyQt6>=6.6.0
29
+ Provides-Extra: cli
30
+ Provides-Extra: desktop
31
+ Requires-Dist: PyQt6>=6.6.0; extra == "desktop"
32
+ Provides-Extra: dev
33
+ Requires-Dist: pytest>=7.0; extra == "dev"
34
+ Requires-Dist: pytest-cov>=4.0; extra == "dev"
35
+ Requires-Dist: black>=24.8.0; extra == "dev"
36
+ Requires-Dist: ruff>=0.15.0; extra == "dev"
37
+ Dynamic: license-file
38
+
39
+ # uDownloader
40
+
41
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/downloads/)
42
+ [![Version 0.1.0](https://img.shields.io/badge/version-0.1.0-green)](./docs/CHANGELOG.md)
43
+ [![License MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
44
+ [![GitHub CI/CD](https://github.com/yourusername/uDownloader/workflows/Tests/badge.svg)](https://github.com/yourusername/uDownloader/actions)
45
+
46
+ A fast, powerful Python application to download YouTube videos or audio. Supports single videos or entire playlists with both CLI and **Desktop GUI**. Uses `yt-dlp` for efficiency and modern format handling.
47
+
48
+ **Available as a pip-installable package!** Install with `pip install udownloader`
49
+
50
+ ## Features
51
+
52
+ ### Core Features
53
+ - Download video or audio from YouTube, Instagram, TikTok, Twitter, and more
54
+ - Process single content or playlists
55
+ - Command-line interface with quality and format options
56
+ - Configuration file support with sensible defaults
57
+ - Detailed progress reporting during downloads
58
+ - Automatic retry logic for failed downloads
59
+ - Platform-specific organization (YouTube, Instagram, Twitter, TikTok, etc.)
60
+
61
+ ### Desktop Application
62
+ - **Modern PyQt6 GUI** for intuitive downloading
63
+ - **Async/Concurrent Downloads** - download multiple videos simultaneously
64
+ - **Download History Tracking** - view all past downloads with statistics
65
+ - **Live Progress Monitoring** - track active downloads in real-time
66
+ - **Queue Management** - manage multiple downloads at once
67
+ - **Settings Panel** - configure quality, output, retries, and concurrent limits
68
+
69
+ ## Installation
70
+
71
+ ### Option 1: Install via pip (Recommended)
72
+
73
+ ```bash
74
+ # From PyPI (when published)
75
+ pip install udownloader
76
+
77
+ # Or install from source (development mode)
78
+ git clone <repository-url>
79
+ cd uDownloader
80
+ pip install -e .
81
+ ```
82
+
83
+ ### Option 2: Manual installation from source
84
+
85
+ ```bash
86
+ git clone <repository-url>
87
+ cd uDownloader
88
+ python3 -m venv venv
89
+ source venv/bin/activate
90
+ pip install -r requirements.txt
91
+ ```
92
+
93
+ After installation, you'll have two commands available:
94
+ - `udownloader` - CLI version
95
+ - `udownloader-desktop` - Desktop GUI version
96
+
97
+
98
+ ## Technology Stack
99
+
100
+ | Component | Technology | Purpose |
101
+ |-----------|-----------|---------|
102
+ | **Language** | Python 3.8+ | Core application |
103
+ | **Video Downloading** | yt-dlp 2024.8.2+ | Format detection & download |
104
+ | **Desktop GUI** | PyQt6 6.6.0+ | Modern graphical interface |
105
+ | **Async Processing** | asyncio + ThreadPoolExecutor | Concurrent downloads |
106
+ | **Configuration** | JSON | User settings persistence |
107
+ | **History Tracking** | JSON | Download records database |
108
+ | **Testing** | pytest + pytest-cov | Unit testing & coverage |
109
+ | **Code Quality** | black + flake8 | Formatting & linting |
110
+ | **Packaging** | setuptools + wheel | PyPI distribution |
111
+ | **CI/CD** | GitHub Actions | Automated testing & publishing |
112
+
113
+ **Key Dependencies:**
114
+ - `yt-dlp` - Video downloading engine
115
+ - `PyQt6` - Desktop application framework
116
+ - `pytest` - Testing framework (dev only)
117
+ - `black` - Code formatter (dev only)
118
+ - `flake8` - Code linter (dev only)
119
+
120
+ ## Quick Start
121
+
122
+ ### CLI Mode
123
+
124
+ ```bash
125
+ # Initialize config file (creates ~/.uDownloader/config.json)
126
+ udownloader --init-config
127
+
128
+ # Download best quality video
129
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID
130
+
131
+ # Download as MP3 audio only
132
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID --audio
133
+
134
+ # Download specific quality (best, 1080p, 720p, 480p, 360p)
135
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID --quality 720p
136
+
137
+ # Download entire playlist to custom location
138
+ udownloader --url https://youtube.com/playlist?list=PLAYLIST_ID --output ~/Downloads --retries 5
139
+
140
+ # Verbose logging for debugging
141
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID --verbose
142
+ ```
143
+
144
+ ### Desktop Application
145
+
146
+ ```bash
147
+ # Launch desktop app (from installed package)
148
+ udownloader-desktop
149
+
150
+ # Or if running from source directory
151
+ python launcher_desktop.py
152
+ ```
153
+
154
+ **Features in Desktop App:**
155
+ - **Download Tab**: Paste URLs and start downloads with quality selection
156
+ - **Queue Tab**: Monitor active downloads in real-time
157
+ - **History Tab**: View all previous downloads with details
158
+ - **Statistics Tab**: See download stats by platform and overall success rate
159
+ - **Settings**: Configure output directory, quality, concurrent limits, and retry attempts
160
+
161
+ ## Configuration
162
+
163
+ The configuration file is automatically created at `~/.uDownloader/config.json` when you run `--init-config`.
164
+
165
+ ### Default Settings:
166
+ ```json
167
+ {
168
+ "output_dir": "uDownload",
169
+ "audio_only": false,
170
+ "video_quality": "best",
171
+ "audio_quality": "192",
172
+ "format_preference": "mp4",
173
+ "max_concurrent_downloads": 1,
174
+ "timeout": 300,
175
+ "retries": 3,
176
+ "verbose": false
177
+ }
178
+ ```
179
+
180
+ You can edit this file directly to change defaults, or override with command-line arguments (CLI) or settings dialog (Desktop app).
181
+
182
+ ## Command-line Options
183
+
184
+ ```
185
+ --url URL, -u URL YouTube video or playlist URL (required for downloads)
186
+ --output OUTPUT, -o OUTPUT Directory to save downloads (default: config or 'uDownload')
187
+ --audio, -a Download audio only (mp3)
188
+ --quality {best,1080p,720p,480p,360p} Video quality preference
189
+ --config CONFIG, -c CONFIG Path to custom config file
190
+ --init-config Create default config file and exit
191
+ --retries RETRIES, -r RETRIES Number of retries on failure (default: 3)
192
+ --verbose, -v Show detailed logging
193
+ --help, -h Show help message
194
+ ```
195
+
196
+ ## Architecture
197
+
198
+ ### Modules
199
+ - **`cli.py`** - Command-line interface
200
+ - **`downloader.py`** - Single download handler
201
+ - **`async_downloader.py`** - Async/concurrent download manager
202
+ - **`desktop.py`** - PyQt6 desktop GUI application
203
+ - **`history.py`** - Download history tracking and statistics
204
+ - **`config.py`** - Configuration management
205
+
206
+ ### Key Features in Code
207
+ - **`AsyncDownloader`** class handles concurrent downloads using ThreadPoolExecutor
208
+ - **`DownloadHistory`** class manages download records in JSON format
209
+ - **`uDownloaderApp`** is the main desktop application with multi-tab interface
210
+ - **`DownloadWorker`** runs downloads in separate thread to keep UI responsive
211
+
212
+ ## Documentation
213
+
214
+ Comprehensive documentation is available in the [docs](docs/) folder:
215
+
216
+ - **[Installation Guide](docs/INSTALLATION.md)** - Platform-specific installation instructions
217
+ - **[Quick Reference](docs/QUICK_REFERENCE.md)** - Commands, workflows, and FAQ
218
+ - **[Contributing Guide](docs/CONTRIBUTING.md)** - Development setup and contribution guidelines
219
+ - **[CI/CD Setup](docs/CICD_SETUP.md)** - GitHub Actions and testing infrastructure
220
+ - **[Changelog](docs/CHANGELOG.md)** - Version history and planned features
221
+ - **[Security Policy](docs/SECURITY.md)** - Vulnerability reporting and security practices
222
+
223
+ ## License
224
+
225
+ uDownloader is licensed under the MIT License - see [LICENSE](LICENSE) file for details.
226
+
227
+ ---
228
+
229
+ **Made with ❤️ for video downloaders everywhere**
@@ -0,0 +1,191 @@
1
+ # uDownloader
2
+
3
+ [![Python 3.8+](https://img.shields.io/badge/python-3.8%2B-blue)](https://www.python.org/downloads/)
4
+ [![Version 0.1.0](https://img.shields.io/badge/version-0.1.0-green)](./docs/CHANGELOG.md)
5
+ [![License MIT](https://img.shields.io/badge/license-MIT-blue)](LICENSE)
6
+ [![GitHub CI/CD](https://github.com/yourusername/uDownloader/workflows/Tests/badge.svg)](https://github.com/yourusername/uDownloader/actions)
7
+
8
+ A fast, powerful Python application to download YouTube videos or audio. Supports single videos or entire playlists with both CLI and **Desktop GUI**. Uses `yt-dlp` for efficiency and modern format handling.
9
+
10
+ **Available as a pip-installable package!** Install with `pip install udownloader`
11
+
12
+ ## Features
13
+
14
+ ### Core Features
15
+ - Download video or audio from YouTube, Instagram, TikTok, Twitter, and more
16
+ - Process single content or playlists
17
+ - Command-line interface with quality and format options
18
+ - Configuration file support with sensible defaults
19
+ - Detailed progress reporting during downloads
20
+ - Automatic retry logic for failed downloads
21
+ - Platform-specific organization (YouTube, Instagram, Twitter, TikTok, etc.)
22
+
23
+ ### Desktop Application
24
+ - **Modern PyQt6 GUI** for intuitive downloading
25
+ - **Async/Concurrent Downloads** - download multiple videos simultaneously
26
+ - **Download History Tracking** - view all past downloads with statistics
27
+ - **Live Progress Monitoring** - track active downloads in real-time
28
+ - **Queue Management** - manage multiple downloads at once
29
+ - **Settings Panel** - configure quality, output, retries, and concurrent limits
30
+
31
+ ## Installation
32
+
33
+ ### Option 1: Install via pip (Recommended)
34
+
35
+ ```bash
36
+ # From PyPI (when published)
37
+ pip install udownloader
38
+
39
+ # Or install from source (development mode)
40
+ git clone <repository-url>
41
+ cd uDownloader
42
+ pip install -e .
43
+ ```
44
+
45
+ ### Option 2: Manual installation from source
46
+
47
+ ```bash
48
+ git clone <repository-url>
49
+ cd uDownloader
50
+ python3 -m venv venv
51
+ source venv/bin/activate
52
+ pip install -r requirements.txt
53
+ ```
54
+
55
+ After installation, you'll have two commands available:
56
+ - `udownloader` - CLI version
57
+ - `udownloader-desktop` - Desktop GUI version
58
+
59
+
60
+ ## Technology Stack
61
+
62
+ | Component | Technology | Purpose |
63
+ |-----------|-----------|---------|
64
+ | **Language** | Python 3.8+ | Core application |
65
+ | **Video Downloading** | yt-dlp 2024.8.2+ | Format detection & download |
66
+ | **Desktop GUI** | PyQt6 6.6.0+ | Modern graphical interface |
67
+ | **Async Processing** | asyncio + ThreadPoolExecutor | Concurrent downloads |
68
+ | **Configuration** | JSON | User settings persistence |
69
+ | **History Tracking** | JSON | Download records database |
70
+ | **Testing** | pytest + pytest-cov | Unit testing & coverage |
71
+ | **Code Quality** | black + flake8 | Formatting & linting |
72
+ | **Packaging** | setuptools + wheel | PyPI distribution |
73
+ | **CI/CD** | GitHub Actions | Automated testing & publishing |
74
+
75
+ **Key Dependencies:**
76
+ - `yt-dlp` - Video downloading engine
77
+ - `PyQt6` - Desktop application framework
78
+ - `pytest` - Testing framework (dev only)
79
+ - `black` - Code formatter (dev only)
80
+ - `flake8` - Code linter (dev only)
81
+
82
+ ## Quick Start
83
+
84
+ ### CLI Mode
85
+
86
+ ```bash
87
+ # Initialize config file (creates ~/.uDownloader/config.json)
88
+ udownloader --init-config
89
+
90
+ # Download best quality video
91
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID
92
+
93
+ # Download as MP3 audio only
94
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID --audio
95
+
96
+ # Download specific quality (best, 1080p, 720p, 480p, 360p)
97
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID --quality 720p
98
+
99
+ # Download entire playlist to custom location
100
+ udownloader --url https://youtube.com/playlist?list=PLAYLIST_ID --output ~/Downloads --retries 5
101
+
102
+ # Verbose logging for debugging
103
+ udownloader --url https://youtube.com/watch?v=VIDEO_ID --verbose
104
+ ```
105
+
106
+ ### Desktop Application
107
+
108
+ ```bash
109
+ # Launch desktop app (from installed package)
110
+ udownloader-desktop
111
+
112
+ # Or if running from source directory
113
+ python launcher_desktop.py
114
+ ```
115
+
116
+ **Features in Desktop App:**
117
+ - **Download Tab**: Paste URLs and start downloads with quality selection
118
+ - **Queue Tab**: Monitor active downloads in real-time
119
+ - **History Tab**: View all previous downloads with details
120
+ - **Statistics Tab**: See download stats by platform and overall success rate
121
+ - **Settings**: Configure output directory, quality, concurrent limits, and retry attempts
122
+
123
+ ## Configuration
124
+
125
+ The configuration file is automatically created at `~/.uDownloader/config.json` when you run `--init-config`.
126
+
127
+ ### Default Settings:
128
+ ```json
129
+ {
130
+ "output_dir": "uDownload",
131
+ "audio_only": false,
132
+ "video_quality": "best",
133
+ "audio_quality": "192",
134
+ "format_preference": "mp4",
135
+ "max_concurrent_downloads": 1,
136
+ "timeout": 300,
137
+ "retries": 3,
138
+ "verbose": false
139
+ }
140
+ ```
141
+
142
+ You can edit this file directly to change defaults, or override with command-line arguments (CLI) or settings dialog (Desktop app).
143
+
144
+ ## Command-line Options
145
+
146
+ ```
147
+ --url URL, -u URL YouTube video or playlist URL (required for downloads)
148
+ --output OUTPUT, -o OUTPUT Directory to save downloads (default: config or 'uDownload')
149
+ --audio, -a Download audio only (mp3)
150
+ --quality {best,1080p,720p,480p,360p} Video quality preference
151
+ --config CONFIG, -c CONFIG Path to custom config file
152
+ --init-config Create default config file and exit
153
+ --retries RETRIES, -r RETRIES Number of retries on failure (default: 3)
154
+ --verbose, -v Show detailed logging
155
+ --help, -h Show help message
156
+ ```
157
+
158
+ ## Architecture
159
+
160
+ ### Modules
161
+ - **`cli.py`** - Command-line interface
162
+ - **`downloader.py`** - Single download handler
163
+ - **`async_downloader.py`** - Async/concurrent download manager
164
+ - **`desktop.py`** - PyQt6 desktop GUI application
165
+ - **`history.py`** - Download history tracking and statistics
166
+ - **`config.py`** - Configuration management
167
+
168
+ ### Key Features in Code
169
+ - **`AsyncDownloader`** class handles concurrent downloads using ThreadPoolExecutor
170
+ - **`DownloadHistory`** class manages download records in JSON format
171
+ - **`uDownloaderApp`** is the main desktop application with multi-tab interface
172
+ - **`DownloadWorker`** runs downloads in separate thread to keep UI responsive
173
+
174
+ ## Documentation
175
+
176
+ Comprehensive documentation is available in the [docs](docs/) folder:
177
+
178
+ - **[Installation Guide](docs/INSTALLATION.md)** - Platform-specific installation instructions
179
+ - **[Quick Reference](docs/QUICK_REFERENCE.md)** - Commands, workflows, and FAQ
180
+ - **[Contributing Guide](docs/CONTRIBUTING.md)** - Development setup and contribution guidelines
181
+ - **[CI/CD Setup](docs/CICD_SETUP.md)** - GitHub Actions and testing infrastructure
182
+ - **[Changelog](docs/CHANGELOG.md)** - Version history and planned features
183
+ - **[Security Policy](docs/SECURITY.md)** - Vulnerability reporting and security practices
184
+
185
+ ## License
186
+
187
+ uDownloader is licensed under the MIT License - see [LICENSE](LICENSE) file for details.
188
+
189
+ ---
190
+
191
+ **Made with ❤️ for video downloaders everywhere**
@@ -0,0 +1,73 @@
1
+ [build-system]
2
+ requires = ["setuptools>=42", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "uDownloader"
7
+ version = "0.1.0"
8
+ description = "Fast, async YouTube/Instagram/TikTok downloader with desktop GUI and CLI"
9
+ readme = "README.md"
10
+ requires-python = ">=3.8"
11
+ license = {text = "MIT"}
12
+ authors = [{name = "Developer"}]
13
+ keywords = ["youtube", "instagram", "downloader", "video", "audio", "desktop"]
14
+ classifiers = [
15
+ "Development Status :: 4 - Beta",
16
+ "Environment :: X11 Applications :: Qt",
17
+ "Intended Audience :: End Users/Desktop",
18
+ "License :: OSI Approved :: MIT License",
19
+ "Programming Language :: Python :: 3",
20
+ "Programming Language :: Python :: 3.8",
21
+ "Programming Language :: Python :: 3.9",
22
+ "Programming Language :: Python :: 3.10",
23
+ "Programming Language :: Python :: 3.11",
24
+ "Programming Language :: Python :: 3.12",
25
+ "Topic :: Multimedia :: Video",
26
+ "Topic :: Utilities",
27
+ ]
28
+
29
+ dependencies = [
30
+ "yt-dlp>=2024.8.2",
31
+ "PyQt6>=6.6.0",
32
+ ]
33
+
34
+ [project.optional-dependencies]
35
+ cli = []
36
+ desktop = ["PyQt6>=6.6.0"]
37
+ dev = [
38
+ "pytest>=7.0",
39
+ "pytest-cov>=4.0",
40
+ "black>=24.8.0",
41
+ "ruff>=0.15.0",
42
+ ]
43
+
44
+ [project.urls]
45
+ Homepage = "https://github.com/yourusername/uDownloader"
46
+ Documentation = "https://github.com/yourusername/uDownloader#readme"
47
+ Repository = "https://github.com/yourusername/uDownloader.git"
48
+ Issues = "https://github.com/yourusername/uDownloader/issues"
49
+
50
+ [project.scripts]
51
+ udownloader = "youdownload.cli:main"
52
+ udownloader-desktop = "youdownload.desktop:main"
53
+
54
+ [tool.setuptools]
55
+ packages = ["youdownload"]
56
+
57
+ [tool.setuptools.package-data]
58
+ youdownload = []
59
+
60
+ [tool.black]
61
+ line-length = 100
62
+ target-version = ['py38', 'py39', 'py310', 'py311', 'py312']
63
+
64
+ [tool.ruff]
65
+ line-length = 100
66
+ target-version = "py38"
67
+
68
+ [tool.pytest.ini_options]
69
+ testpaths = ["tests"]
70
+ python_files = ["test_*.py"]
71
+
72
+ [tool.ruff.lint]
73
+ select = ["E", "F", "W"] # pycodestyle, Pyflakes, warnings
@@ -0,0 +1,2 @@
1
+ yt-dlp>=2024.8.2
2
+ PyQt6>=6.6.0
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Setup script for uDownloader.
4
+ Modern approach using pyproject.toml is preferred.
5
+ This file exists for compatibility.
6
+ """
7
+
8
+ from setuptools import setup
9
+
10
+ setup()
@@ -0,0 +1,149 @@
1
+ """Tests for youdownload package."""
2
+
3
+ import pytest
4
+ from youdownload import __version__
5
+ from youdownload.config import load_config, DEFAULT_CONFIG
6
+ from youdownload.history import DownloadHistory
7
+ from youdownload.async_downloader import AsyncDownloader
8
+ from pathlib import Path
9
+ import tempfile
10
+
11
+
12
+ class TestVersion:
13
+ """Test package version."""
14
+
15
+ def test_version_exists(self):
16
+ """Test that version is defined."""
17
+ assert __version__ is not None
18
+ assert isinstance(__version__, str)
19
+
20
+ def test_version_format(self):
21
+ """Test version follows semantic versioning."""
22
+ parts = __version__.split(".")
23
+ assert len(parts) >= 2
24
+
25
+
26
+ class TestConfig:
27
+ """Test configuration management."""
28
+
29
+ def test_default_config_structure(self):
30
+ """Test default config has required keys."""
31
+ required_keys = [
32
+ "output_dir",
33
+ "audio_only",
34
+ "video_quality",
35
+ "audio_quality",
36
+ "max_concurrent_downloads",
37
+ "retries",
38
+ ]
39
+ for key in required_keys:
40
+ assert key in DEFAULT_CONFIG
41
+
42
+ def test_load_config_with_no_file(self):
43
+ """Test loading config returns defaults when no file exists."""
44
+ # Use temp file that doesn't exist
45
+ config = load_config("/tmp/nonexistent_config_12345.json")
46
+ assert config["output_dir"] == "uDownload"
47
+ assert config["video_quality"] == "best"
48
+
49
+
50
+ class TestHistory:
51
+ """Test download history tracking."""
52
+
53
+ def test_history_initialization(self):
54
+ """Test history object initializes correctly."""
55
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
56
+ history_file = Path(f.name)
57
+
58
+ try:
59
+ history = DownloadHistory(history_file)
60
+ assert history.history_file == history_file
61
+ assert history_file.exists()
62
+ finally:
63
+ if history_file.exists():
64
+ history_file.unlink()
65
+
66
+ def test_add_and_get_history(self):
67
+ """Test adding and retrieving history."""
68
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
69
+ history_file = Path(f.name)
70
+
71
+ try:
72
+ history = DownloadHistory(history_file)
73
+
74
+ record = {
75
+ "title": "Test Video",
76
+ "platform": "YouTube",
77
+ "url": "https://youtube.com/watch?v=test",
78
+ "success": True,
79
+ }
80
+
81
+ history.add_download(record)
82
+ records = history.get_history()
83
+
84
+ assert len(records) > 0
85
+ assert records[0]["title"] == "Test Video"
86
+ finally:
87
+ if history_file.exists():
88
+ history_file.unlink()
89
+
90
+ def test_get_stats(self):
91
+ """Test statistics calculation."""
92
+ with tempfile.NamedTemporaryFile(mode="w", suffix=".json", delete=False) as f:
93
+ history_file = Path(f.name)
94
+
95
+ try:
96
+ history = DownloadHistory(history_file)
97
+
98
+ # Add test records
99
+ history.add_download(
100
+ {
101
+ "title": "Video 1",
102
+ "platform": "YouTube",
103
+ "url": "https://example.com",
104
+ "success": True,
105
+ }
106
+ )
107
+ history.add_download(
108
+ {
109
+ "title": "Video 2",
110
+ "platform": "Instagram",
111
+ "url": "https://example.com",
112
+ "success": False,
113
+ }
114
+ )
115
+
116
+ stats = history.get_stats()
117
+ assert stats["total_downloads"] == 2
118
+ assert stats["successful"] == 1
119
+ assert stats["failed"] == 1
120
+ finally:
121
+ if history_file.exists():
122
+ history_file.unlink()
123
+
124
+
125
+ class TestAsyncDownloader:
126
+ """Test async downloader."""
127
+
128
+ def test_initialization(self):
129
+ """Test AsyncDownloader initializes correctly."""
130
+ downloader = AsyncDownloader(max_concurrent=2)
131
+ assert downloader.max_concurrent == 2
132
+ assert downloader.executor is not None
133
+
134
+ def test_platform_detection(self):
135
+ """Test platform detection."""
136
+ downloader = AsyncDownloader()
137
+
138
+ assert downloader.detect_platform("https://youtube.com/watch?v=test") == "YouTube"
139
+ assert downloader.detect_platform("https://youtu.be/test") == "YouTube"
140
+ assert downloader.detect_platform("https://instagram.com/p/test") == "Instagram"
141
+ assert downloader.detect_platform("https://tiktok.com/@user/video/123") == "TikTok"
142
+ assert downloader.detect_platform("https://twitter.com/user/status/123") == "Twitter"
143
+ assert downloader.detect_platform("https://x.com/user/status/123") == "Twitter"
144
+ assert downloader.detect_platform("https://vimeo.com/123") == "Vimeo"
145
+ assert downloader.detect_platform("https://facebook.com/video/123") == "Facebook"
146
+
147
+
148
+ if __name__ == "__main__":
149
+ pytest.main([__file__, "-v"])