woolly 0.2.0__tar.gz → 0.3.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.
Files changed (58) hide show
  1. woolly-0.3.0/PKG-INFO +322 -0
  2. woolly-0.3.0/README.md +292 -0
  3. woolly-0.3.0/tests/functional/test_optional_flag.py +277 -0
  4. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_commands/test_check.py +43 -16
  5. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_languages/test_python.py +3 -1
  6. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_languages/test_registry.py +10 -10
  7. woolly-0.3.0/tests/unit/test_optional_dependencies.py +383 -0
  8. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_reporters/test_base.py +116 -41
  9. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_reporters/test_json.py +22 -13
  10. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_reporters/test_markdown.py +0 -46
  11. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_reporters/test_registry.py +9 -9
  12. {woolly-0.2.0 → woolly-0.3.0}/woolly/cache.py +15 -5
  13. {woolly-0.2.0 → woolly-0.3.0}/woolly/commands/check.py +107 -43
  14. {woolly-0.2.0 → woolly-0.3.0}/woolly/commands/list_formats.py +3 -3
  15. {woolly-0.2.0 → woolly-0.3.0}/woolly/commands/list_languages.py +4 -4
  16. woolly-0.3.0/woolly/http.py +34 -0
  17. {woolly-0.2.0 → woolly-0.3.0}/woolly/languages/__init__.py +33 -3
  18. {woolly-0.2.0 → woolly-0.3.0}/woolly/languages/base.py +11 -7
  19. {woolly-0.2.0 → woolly-0.3.0}/woolly/languages/python.py +5 -6
  20. {woolly-0.2.0 → woolly-0.3.0}/woolly/languages/rust.py +3 -5
  21. {woolly-0.2.0 → woolly-0.3.0}/woolly/reporters/__init__.py +29 -8
  22. {woolly-0.2.0 → woolly-0.3.0}/woolly/reporters/base.py +92 -10
  23. woolly-0.3.0/woolly/reporters/json.py +175 -0
  24. {woolly-0.2.0 → woolly-0.3.0}/woolly/reporters/markdown.py +30 -53
  25. {woolly-0.2.0 → woolly-0.3.0}/woolly/reporters/stdout.py +27 -6
  26. woolly-0.2.0/PKG-INFO +0 -213
  27. woolly-0.2.0/README.md +0 -183
  28. woolly-0.2.0/woolly/reporters/json.py +0 -145
  29. {woolly-0.2.0 → woolly-0.3.0}/.coverage +0 -0
  30. {woolly-0.2.0 → woolly-0.3.0}/.github/workflows/lint.yml +0 -0
  31. {woolly-0.2.0 → woolly-0.3.0}/.github/workflows/publish.yml +0 -0
  32. {woolly-0.2.0 → woolly-0.3.0}/.github/workflows/tests.yml +0 -0
  33. {woolly-0.2.0 → woolly-0.3.0}/.gitignore +0 -0
  34. {woolly-0.2.0 → woolly-0.3.0}/.python-version +0 -0
  35. {woolly-0.2.0 → woolly-0.3.0}/LICENSE +0 -0
  36. {woolly-0.2.0 → woolly-0.3.0}/pyproject.toml +0 -0
  37. {woolly-0.2.0 → woolly-0.3.0}/tests/__init__.py +0 -0
  38. {woolly-0.2.0 → woolly-0.3.0}/tests/conftest.py +0 -0
  39. {woolly-0.2.0 → woolly-0.3.0}/tests/functional/__init__.py +0 -0
  40. {woolly-0.2.0 → woolly-0.3.0}/tests/functional/test_cli.py +0 -0
  41. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/__init__.py +0 -0
  42. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_cache.py +0 -0
  43. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_commands/__init__.py +0 -0
  44. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_commands/test_other_commands.py +0 -0
  45. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_debug.py +0 -0
  46. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_languages/__init__.py +0 -0
  47. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_languages/test_base.py +0 -0
  48. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_languages/test_rust.py +0 -0
  49. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_progress.py +0 -0
  50. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_reporters/__init__.py +0 -0
  51. {woolly-0.2.0 → woolly-0.3.0}/tests/unit/test_reporters/test_stdout.py +0 -0
  52. {woolly-0.2.0 → woolly-0.3.0}/uv.lock +0 -0
  53. {woolly-0.2.0 → woolly-0.3.0}/woolly/__init__.py +0 -0
  54. {woolly-0.2.0 → woolly-0.3.0}/woolly/__main__.py +0 -0
  55. {woolly-0.2.0 → woolly-0.3.0}/woolly/commands/__init__.py +0 -0
  56. {woolly-0.2.0 → woolly-0.3.0}/woolly/commands/clear_cache.py +0 -0
  57. {woolly-0.2.0 → woolly-0.3.0}/woolly/debug.py +0 -0
  58. {woolly-0.2.0 → woolly-0.3.0}/woolly/progress.py +0 -0
woolly-0.3.0/PKG-INFO ADDED
@@ -0,0 +1,322 @@
1
+ Metadata-Version: 2.4
2
+ Name: woolly
3
+ Version: 0.3.0
4
+ Summary: Check if package dependencies are available in Fedora. Supports Rust, Python, and more.
5
+ Author-email: Rodolfo Olivieri <rodolfo.olivieri3@gmail.com>
6
+ License-File: LICENSE
7
+ Classifier: Development Status :: 2 - Pre-Alpha
8
+ Classifier: Environment :: Console
9
+ Classifier: Intended Audience :: Developers
10
+ Classifier: Intended Audience :: Information Technology
11
+ Classifier: Intended Audience :: System Administrators
12
+ Classifier: License :: OSI Approved :: MIT License
13
+ Classifier: Natural Language :: English
14
+ Classifier: Operating System :: POSIX :: Linux
15
+ Classifier: Programming Language :: Python :: 3
16
+ Classifier: Programming Language :: Python :: 3 :: Only
17
+ Classifier: Programming Language :: Python :: 3.10
18
+ Classifier: Programming Language :: Python :: 3.11
19
+ Classifier: Programming Language :: Python :: 3.12
20
+ Classifier: Programming Language :: Python :: 3.13
21
+ Classifier: Programming Language :: Python :: 3.14
22
+ Classifier: Topic :: System :: Systems Administration
23
+ Classifier: Topic :: Utilities
24
+ Requires-Python: >=3.10
25
+ Requires-Dist: cyclopts>=4.3.0
26
+ Requires-Dist: httpx>=0.28.0
27
+ Requires-Dist: pydantic>=2.10.0
28
+ Requires-Dist: rich>=14.2.0
29
+ Description-Content-Type: text/markdown
30
+
31
+ # 🐑 Woolly
32
+
33
+ **Check if package dependencies are available in Fedora.**
34
+
35
+ Woolly analyzes package dependencies from various language ecosystems and checks their availability in Fedora repositories, helping packagers estimate the effort needed to bring a package to Fedora.
36
+
37
+ > ⚠️ **Experimental Software**
38
+ >
39
+ > This project is still experimental and may not get things right all the time.
40
+ > Results should be verified manually, especially for complex dependency trees.
41
+ > Platform-specific dependencies (like `windows-*` crates) may be flagged as missing
42
+ > even though they're not needed on Linux.
43
+
44
+ ## What does "woolly" mean?
45
+
46
+ Nothing. I just liked the name. 🐑
47
+
48
+ ## Features
49
+
50
+ - **Multi-language support** — Analyze dependencies from Rust (crates.io) and Python (PyPI)
51
+ - **Multiple output formats** — Console output, JSON, and Markdown reports
52
+ - **Optional dependency tracking** — Optionally include and separately track optional dependencies
53
+ - **Smart caching** — Caches API responses and dnf queries to speed up repeated analyses
54
+ - **Progress tracking** — Real-time progress bar showing analysis status
55
+ - **Debug logging** — Verbose logging mode for troubleshooting
56
+ - **Extensible architecture** — Easy to add new languages and report formats
57
+
58
+ ## Supported Languages
59
+
60
+ | Language | Registry | CLI Flag | Aliases |
61
+ |----------|-----------|-----------------------|-------------------------|
62
+ | Rust | crates.io | `--lang rust` | `-l rs`, `-l crate` |
63
+ | Python | PyPI | `--lang python` | `-l py`, `-l pypi` |
64
+
65
+ ## Output Formats
66
+
67
+ | Format | Description | CLI Flag | Aliases |
68
+ |----------|----------------------------------|----------------------|----------------------|
69
+ | stdout | Rich console output (default) | `--report stdout` | `-r console` |
70
+ | json | JSON file for programmatic use | `--report json` | |
71
+ | markdown | Markdown file for documentation | `--report markdown` | `-r md` |
72
+
73
+ ## Installation
74
+
75
+ ```bash
76
+ # Using uv (recommended)
77
+ uv pip install .
78
+
79
+ # Or run directly without installing
80
+ uv run woolly --help
81
+
82
+ # Using pip
83
+ pip install .
84
+ ```
85
+
86
+ ### Requirements
87
+
88
+ - Python 3.10+
89
+ - `dnf` available on the system (for Fedora package queries)
90
+
91
+ ## Usage
92
+
93
+ ### Basic Usage
94
+
95
+ ```bash
96
+ # Check a Rust crate (default language)
97
+ woolly check ripgrep
98
+
99
+ # Check a Python package
100
+ woolly check --lang python requests
101
+
102
+ # Use language aliases
103
+ woolly check -l py flask
104
+ woolly check -l rs tokio
105
+ ```
106
+
107
+ ### Options
108
+
109
+ ```bash
110
+ # Check a specific version
111
+ woolly check serde --version 1.0.200
112
+
113
+ # Include optional dependencies in the analysis
114
+ woolly check --optional requests -l python
115
+
116
+ # Limit recursion depth
117
+ woolly check --max-depth 10 tokio
118
+
119
+ # Disable progress bar
120
+ woolly check --no-progress serde
121
+
122
+ # Enable debug logging
123
+ woolly check --debug flask -l py
124
+
125
+ # Output as JSON
126
+ woolly check --report json serde
127
+
128
+ # Output as Markdown
129
+ woolly check -r md requests -l py
130
+ ```
131
+
132
+ ### Other Commands
133
+
134
+ ```bash
135
+ # List available languages
136
+ woolly list-languages
137
+
138
+ # List available output formats
139
+ woolly list-formats
140
+
141
+ # Clear the cache
142
+ woolly clear-cache
143
+ ```
144
+
145
+ ## Example Output
146
+
147
+ ### Rust
148
+
149
+ ```bash
150
+ $ woolly check cliclack
151
+
152
+ Analyzing Rust package: cliclack
153
+ Registry: crates.io
154
+ Cache directory: /home/user/.cache/woolly
155
+
156
+ Analyzing Rust dependencies ━━━━━━━━━━━━━━━━━ 100% • 0:00:15 complete!
157
+
158
+ Dependency Summary for 'cliclack' (Rust)
159
+ ╭────────────────────────────┬───────╮
160
+ │ Metric │ Value │
161
+ ├────────────────────────────┼───────┤
162
+ │ Total dependencies checked │ 7 │
163
+ │ Packaged in Fedora │ 0 │
164
+ │ Missing from Fedora │ 1 │
165
+ ╰────────────────────────────┴───────╯
166
+
167
+ Missing packages that need packaging:
168
+ • cliclack
169
+
170
+ Dependency Tree:
171
+ cliclack v0.3.6 • ✗ not packaged
172
+ ├── console v0.16.1 • ✓ packaged (0.16.1)
173
+ │ ├── encode_unicode v1.0.0 • ✓ packaged (1.0.0)
174
+ │ └── windows-sys v0.61.2 • ✗ not packaged
175
+ ...
176
+ ```
177
+
178
+ ### Python
179
+
180
+ ```bash
181
+ $ woolly check --lang python requests
182
+
183
+ Analyzing Python package: requests
184
+ Registry: PyPI
185
+ Cache directory: /home/user/.cache/woolly
186
+
187
+ Analyzing Python dependencies ━━━━━━━━━━━━━━ 100% • 0:00:05 complete!
188
+
189
+ Dependency Summary for 'requests' (Python)
190
+ ╭────────────────────────────┬───────╮
191
+ │ Metric │ Value │
192
+ ├────────────────────────────┼───────┤
193
+ │ Total dependencies checked │ 5 │
194
+ │ Packaged in Fedora │ 5 │
195
+ │ Missing from Fedora │ 0 │
196
+ ╰────────────────────────────┴───────╯
197
+
198
+ Dependency Tree:
199
+ requests v2.32.3 • ✓ packaged (2.32.3) [python3-requests]
200
+ ├── charset-normalizer v3.4.0 • ✓ packaged (3.4.0) [python3-charset-normalizer]
201
+ ├── idna v3.10 • ✓ packaged (3.10) [python3-idna]
202
+ ├── urllib3 v2.2.3 • ✓ packaged (2.2.3) [python3-urllib3]
203
+ └── certifi v2024.8.30 • ✓ packaged (2024.8.30) [python3-certifi]
204
+ ```
205
+
206
+ ### With Optional Dependencies
207
+
208
+ ```bash
209
+ $ woolly check --lang python --optional flask
210
+
211
+ Dependency Summary for 'flask' (Python)
212
+ ╭────────────────────────────┬───────╮
213
+ │ Metric │ Value │
214
+ ├────────────────────────────┼───────┤
215
+ │ Total dependencies checked │ 15 │
216
+ │ Packaged in Fedora │ 12 │
217
+ │ Missing from Fedora │ 3 │
218
+ │ │ │
219
+ │ Optional dependencies │ 4 │
220
+ │ ├─ Packaged │ 2 │
221
+ │ └─ Missing │ 2 │
222
+ ╰────────────────────────────┴───────╯
223
+ ```
224
+
225
+ ## Adding a New Language
226
+
227
+ To add support for a new language, create a new provider in `woolly/languages/`:
228
+
229
+ ```python
230
+ # woolly/languages/go.py
231
+ from typing import Optional
232
+
233
+ from woolly.languages.base import Dependency, LanguageProvider, PackageInfo
234
+
235
+
236
+ class GoProvider(LanguageProvider):
237
+ """Provider for Go modules."""
238
+
239
+ # Required class attributes
240
+ name = "go"
241
+ display_name = "Go"
242
+ registry_name = "Go Modules"
243
+ fedora_provides_prefix = "golang"
244
+ cache_namespace = "go"
245
+
246
+ # Required methods to implement:
247
+
248
+ def fetch_package_info(self, package_name: str) -> Optional[PackageInfo]:
249
+ """Fetch package info from proxy.golang.org."""
250
+ ...
251
+
252
+ def fetch_dependencies(self, package_name: str, version: str) -> list[Dependency]:
253
+ """Fetch dependencies from go.mod."""
254
+ ...
255
+
256
+ # Optional: Override these if your language has special naming conventions
257
+
258
+ def normalize_package_name(self, package_name: str) -> str:
259
+ """Normalize package name for Fedora lookup."""
260
+ return package_name
261
+
262
+ def get_alternative_names(self, package_name: str) -> list[str]:
263
+ """Alternative names to try if package not found."""
264
+ return []
265
+ ```
266
+
267
+ Then register it in `woolly/languages/__init__.py`:
268
+
269
+ ```python
270
+ from woolly.languages.go import GoProvider
271
+
272
+ PROVIDERS: dict[str, type[LanguageProvider]] = {
273
+ "rust": RustProvider,
274
+ "python": PythonProvider,
275
+ "go": GoProvider, # Add new provider
276
+ }
277
+
278
+ ALIASES: dict[str, str] = {
279
+ # ... existing aliases
280
+ "golang": "go",
281
+ }
282
+ ```
283
+
284
+ ## Adding a New Output Format
285
+
286
+ To add a new output format, create a reporter in `woolly/reporters/`:
287
+
288
+ ```python
289
+ # woolly/reporters/html.py
290
+ from woolly.reporters.base import Reporter, ReportData
291
+
292
+
293
+ class HtmlReporter(Reporter):
294
+ """HTML report with interactive tree."""
295
+
296
+ name = "html"
297
+ description = "HTML report with interactive dependency tree"
298
+ file_extension = "html"
299
+ writes_to_file = True
300
+
301
+ def generate(self, data: ReportData) -> str:
302
+ """Generate HTML content."""
303
+ ...
304
+ ```
305
+
306
+ Then register it in `woolly/reporters/__init__.py`.
307
+
308
+ ## Notes
309
+
310
+ - Results should be verified manually — some packages may have different names in Fedora
311
+ - Platform-specific dependencies (like `windows-*` crates) are shown as missing but aren't needed on Linux
312
+ - The tool uses `dnf repoquery` to check Fedora packages, so it must run on a Fedora system or have access to Fedora repos
313
+ - Cache is stored in `~/.cache/woolly` and can be cleared with `woolly clear-cache`
314
+
315
+ ## License
316
+
317
+ MIT License — see [LICENSE](LICENSE) for details.
318
+
319
+ ## Credits
320
+
321
+ - **[Rodolfo Olivieri (@r0x0d)](https://github.com/r0x0d)** — Creator and maintainer
322
+ - **[Claude](https://claude.ai)** — AI pair programmer by [Anthropic](https://anthropic.com)
woolly-0.3.0/README.md ADDED
@@ -0,0 +1,292 @@
1
+ # 🐑 Woolly
2
+
3
+ **Check if package dependencies are available in Fedora.**
4
+
5
+ Woolly analyzes package dependencies from various language ecosystems and checks their availability in Fedora repositories, helping packagers estimate the effort needed to bring a package to Fedora.
6
+
7
+ > ⚠️ **Experimental Software**
8
+ >
9
+ > This project is still experimental and may not get things right all the time.
10
+ > Results should be verified manually, especially for complex dependency trees.
11
+ > Platform-specific dependencies (like `windows-*` crates) may be flagged as missing
12
+ > even though they're not needed on Linux.
13
+
14
+ ## What does "woolly" mean?
15
+
16
+ Nothing. I just liked the name. 🐑
17
+
18
+ ## Features
19
+
20
+ - **Multi-language support** — Analyze dependencies from Rust (crates.io) and Python (PyPI)
21
+ - **Multiple output formats** — Console output, JSON, and Markdown reports
22
+ - **Optional dependency tracking** — Optionally include and separately track optional dependencies
23
+ - **Smart caching** — Caches API responses and dnf queries to speed up repeated analyses
24
+ - **Progress tracking** — Real-time progress bar showing analysis status
25
+ - **Debug logging** — Verbose logging mode for troubleshooting
26
+ - **Extensible architecture** — Easy to add new languages and report formats
27
+
28
+ ## Supported Languages
29
+
30
+ | Language | Registry | CLI Flag | Aliases |
31
+ |----------|-----------|-----------------------|-------------------------|
32
+ | Rust | crates.io | `--lang rust` | `-l rs`, `-l crate` |
33
+ | Python | PyPI | `--lang python` | `-l py`, `-l pypi` |
34
+
35
+ ## Output Formats
36
+
37
+ | Format | Description | CLI Flag | Aliases |
38
+ |----------|----------------------------------|----------------------|----------------------|
39
+ | stdout | Rich console output (default) | `--report stdout` | `-r console` |
40
+ | json | JSON file for programmatic use | `--report json` | |
41
+ | markdown | Markdown file for documentation | `--report markdown` | `-r md` |
42
+
43
+ ## Installation
44
+
45
+ ```bash
46
+ # Using uv (recommended)
47
+ uv pip install .
48
+
49
+ # Or run directly without installing
50
+ uv run woolly --help
51
+
52
+ # Using pip
53
+ pip install .
54
+ ```
55
+
56
+ ### Requirements
57
+
58
+ - Python 3.10+
59
+ - `dnf` available on the system (for Fedora package queries)
60
+
61
+ ## Usage
62
+
63
+ ### Basic Usage
64
+
65
+ ```bash
66
+ # Check a Rust crate (default language)
67
+ woolly check ripgrep
68
+
69
+ # Check a Python package
70
+ woolly check --lang python requests
71
+
72
+ # Use language aliases
73
+ woolly check -l py flask
74
+ woolly check -l rs tokio
75
+ ```
76
+
77
+ ### Options
78
+
79
+ ```bash
80
+ # Check a specific version
81
+ woolly check serde --version 1.0.200
82
+
83
+ # Include optional dependencies in the analysis
84
+ woolly check --optional requests -l python
85
+
86
+ # Limit recursion depth
87
+ woolly check --max-depth 10 tokio
88
+
89
+ # Disable progress bar
90
+ woolly check --no-progress serde
91
+
92
+ # Enable debug logging
93
+ woolly check --debug flask -l py
94
+
95
+ # Output as JSON
96
+ woolly check --report json serde
97
+
98
+ # Output as Markdown
99
+ woolly check -r md requests -l py
100
+ ```
101
+
102
+ ### Other Commands
103
+
104
+ ```bash
105
+ # List available languages
106
+ woolly list-languages
107
+
108
+ # List available output formats
109
+ woolly list-formats
110
+
111
+ # Clear the cache
112
+ woolly clear-cache
113
+ ```
114
+
115
+ ## Example Output
116
+
117
+ ### Rust
118
+
119
+ ```bash
120
+ $ woolly check cliclack
121
+
122
+ Analyzing Rust package: cliclack
123
+ Registry: crates.io
124
+ Cache directory: /home/user/.cache/woolly
125
+
126
+ Analyzing Rust dependencies ━━━━━━━━━━━━━━━━━ 100% • 0:00:15 complete!
127
+
128
+ Dependency Summary for 'cliclack' (Rust)
129
+ ╭────────────────────────────┬───────╮
130
+ │ Metric │ Value │
131
+ ├────────────────────────────┼───────┤
132
+ │ Total dependencies checked │ 7 │
133
+ │ Packaged in Fedora │ 0 │
134
+ │ Missing from Fedora │ 1 │
135
+ ╰────────────────────────────┴───────╯
136
+
137
+ Missing packages that need packaging:
138
+ • cliclack
139
+
140
+ Dependency Tree:
141
+ cliclack v0.3.6 • ✗ not packaged
142
+ ├── console v0.16.1 • ✓ packaged (0.16.1)
143
+ │ ├── encode_unicode v1.0.0 • ✓ packaged (1.0.0)
144
+ │ └── windows-sys v0.61.2 • ✗ not packaged
145
+ ...
146
+ ```
147
+
148
+ ### Python
149
+
150
+ ```bash
151
+ $ woolly check --lang python requests
152
+
153
+ Analyzing Python package: requests
154
+ Registry: PyPI
155
+ Cache directory: /home/user/.cache/woolly
156
+
157
+ Analyzing Python dependencies ━━━━━━━━━━━━━━ 100% • 0:00:05 complete!
158
+
159
+ Dependency Summary for 'requests' (Python)
160
+ ╭────────────────────────────┬───────╮
161
+ │ Metric │ Value │
162
+ ├────────────────────────────┼───────┤
163
+ │ Total dependencies checked │ 5 │
164
+ │ Packaged in Fedora │ 5 │
165
+ │ Missing from Fedora │ 0 │
166
+ ╰────────────────────────────┴───────╯
167
+
168
+ Dependency Tree:
169
+ requests v2.32.3 • ✓ packaged (2.32.3) [python3-requests]
170
+ ├── charset-normalizer v3.4.0 • ✓ packaged (3.4.0) [python3-charset-normalizer]
171
+ ├── idna v3.10 • ✓ packaged (3.10) [python3-idna]
172
+ ├── urllib3 v2.2.3 • ✓ packaged (2.2.3) [python3-urllib3]
173
+ └── certifi v2024.8.30 • ✓ packaged (2024.8.30) [python3-certifi]
174
+ ```
175
+
176
+ ### With Optional Dependencies
177
+
178
+ ```bash
179
+ $ woolly check --lang python --optional flask
180
+
181
+ Dependency Summary for 'flask' (Python)
182
+ ╭────────────────────────────┬───────╮
183
+ │ Metric │ Value │
184
+ ├────────────────────────────┼───────┤
185
+ │ Total dependencies checked │ 15 │
186
+ │ Packaged in Fedora │ 12 │
187
+ │ Missing from Fedora │ 3 │
188
+ │ │ │
189
+ │ Optional dependencies │ 4 │
190
+ │ ├─ Packaged │ 2 │
191
+ │ └─ Missing │ 2 │
192
+ ╰────────────────────────────┴───────╯
193
+ ```
194
+
195
+ ## Adding a New Language
196
+
197
+ To add support for a new language, create a new provider in `woolly/languages/`:
198
+
199
+ ```python
200
+ # woolly/languages/go.py
201
+ from typing import Optional
202
+
203
+ from woolly.languages.base import Dependency, LanguageProvider, PackageInfo
204
+
205
+
206
+ class GoProvider(LanguageProvider):
207
+ """Provider for Go modules."""
208
+
209
+ # Required class attributes
210
+ name = "go"
211
+ display_name = "Go"
212
+ registry_name = "Go Modules"
213
+ fedora_provides_prefix = "golang"
214
+ cache_namespace = "go"
215
+
216
+ # Required methods to implement:
217
+
218
+ def fetch_package_info(self, package_name: str) -> Optional[PackageInfo]:
219
+ """Fetch package info from proxy.golang.org."""
220
+ ...
221
+
222
+ def fetch_dependencies(self, package_name: str, version: str) -> list[Dependency]:
223
+ """Fetch dependencies from go.mod."""
224
+ ...
225
+
226
+ # Optional: Override these if your language has special naming conventions
227
+
228
+ def normalize_package_name(self, package_name: str) -> str:
229
+ """Normalize package name for Fedora lookup."""
230
+ return package_name
231
+
232
+ def get_alternative_names(self, package_name: str) -> list[str]:
233
+ """Alternative names to try if package not found."""
234
+ return []
235
+ ```
236
+
237
+ Then register it in `woolly/languages/__init__.py`:
238
+
239
+ ```python
240
+ from woolly.languages.go import GoProvider
241
+
242
+ PROVIDERS: dict[str, type[LanguageProvider]] = {
243
+ "rust": RustProvider,
244
+ "python": PythonProvider,
245
+ "go": GoProvider, # Add new provider
246
+ }
247
+
248
+ ALIASES: dict[str, str] = {
249
+ # ... existing aliases
250
+ "golang": "go",
251
+ }
252
+ ```
253
+
254
+ ## Adding a New Output Format
255
+
256
+ To add a new output format, create a reporter in `woolly/reporters/`:
257
+
258
+ ```python
259
+ # woolly/reporters/html.py
260
+ from woolly.reporters.base import Reporter, ReportData
261
+
262
+
263
+ class HtmlReporter(Reporter):
264
+ """HTML report with interactive tree."""
265
+
266
+ name = "html"
267
+ description = "HTML report with interactive dependency tree"
268
+ file_extension = "html"
269
+ writes_to_file = True
270
+
271
+ def generate(self, data: ReportData) -> str:
272
+ """Generate HTML content."""
273
+ ...
274
+ ```
275
+
276
+ Then register it in `woolly/reporters/__init__.py`.
277
+
278
+ ## Notes
279
+
280
+ - Results should be verified manually — some packages may have different names in Fedora
281
+ - Platform-specific dependencies (like `windows-*` crates) are shown as missing but aren't needed on Linux
282
+ - The tool uses `dnf repoquery` to check Fedora packages, so it must run on a Fedora system or have access to Fedora repos
283
+ - Cache is stored in `~/.cache/woolly` and can be cleared with `woolly clear-cache`
284
+
285
+ ## License
286
+
287
+ MIT License — see [LICENSE](LICENSE) for details.
288
+
289
+ ## Credits
290
+
291
+ - **[Rodolfo Olivieri (@r0x0d)](https://github.com/r0x0d)** — Creator and maintainer
292
+ - **[Claude](https://claude.ai)** — AI pair programmer by [Anthropic](https://anthropic.com)