pdf-file-renamer 0.5.0__tar.gz → 0.6.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.
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/PKG-INFO +38 -10
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/README.md +36 -9
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/coverage.xml +230 -102
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/pyproject.toml +3 -1
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/__init__.py +1 -1
- pdf_file_renamer-0.6.0/src/pdf_file_renamer/application/filename_service.py +172 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/application/pdf_rename_workflow.py +27 -2
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/domain/models.py +29 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/domain/ports.py +18 -1
- pdf_file_renamer-0.6.0/src/pdf_file_renamer/infrastructure/doi/__init__.py +5 -0
- pdf_file_renamer-0.6.0/src/pdf_file_renamer/infrastructure/doi/pdf2doi_extractor.py +129 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/presentation/cli.py +5 -0
- pdf_file_renamer-0.5.0/src/pdf_file_renamer/application/filename_service.py +0 -70
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/.env.example +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/.github/workflows/ci.yml +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/.github/workflows/release.yml +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/.gitignore +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/.python-version +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/LICENSE +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/REFACTORING_SUMMARY.md +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/application/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/application/rename_service.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/domain/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/config.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/llm/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/llm/pydantic_ai_provider.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/pdf/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/pdf/composite.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/pdf/docling_extractor.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/infrastructure/pdf/pymupdf_extractor.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/main.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/presentation/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/src/pdf_file_renamer/presentation/formatters.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/__init__.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/data/2025-dennis-managing-complexity.pdf +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/data/Camp_of_the_Saints.pdf +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/data/s43588-025-00854-1.pdf +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/test_domain_models.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/test_filename_service.py +0 -0
- {pdf_file_renamer-0.5.0 → pdf_file_renamer-0.6.0}/tests/test_rename_service.py +0 -0
@@ -1,11 +1,12 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: pdf-file-renamer
|
3
|
-
Version: 0.
|
3
|
+
Version: 0.6.0
|
4
4
|
Summary: Intelligent PDF renaming using LLMs
|
5
5
|
License-File: LICENSE
|
6
6
|
Requires-Python: >=3.11
|
7
7
|
Requires-Dist: docling-core>=2.0.0
|
8
8
|
Requires-Dist: docling-parse>=2.0.0
|
9
|
+
Requires-Dist: pdf2doi>=1.7
|
9
10
|
Requires-Dist: pydantic-ai>=1.0.17
|
10
11
|
Requires-Dist: pydantic-settings>=2.7.1
|
11
12
|
Requires-Dist: pydantic>=2.10.6
|
@@ -43,9 +44,11 @@ Intelligent PDF file renaming using LLMs. This tool analyzes PDF content and met
|
|
43
44
|
|
44
45
|
## Features
|
45
46
|
|
47
|
+
- **DOI-based naming** - Automatically extracts DOI and fetches authoritative metadata for academic papers
|
46
48
|
- **Advanced PDF parsing** using docling-parse for better structure-aware extraction
|
47
49
|
- **OCR fallback** for scanned PDFs with low text content
|
48
50
|
- **Smart LLM prompting** with multi-pass analysis for improved accuracy
|
51
|
+
- **Hybrid approach** - Uses DOI metadata when available, falls back to LLM analysis for other documents
|
49
52
|
- Suggests filenames in format: `Author-Topic-Year.pdf`
|
50
53
|
- Dry-run mode to preview changes before applying
|
51
54
|
- **Enhanced interactive mode** with options to accept, manually edit, retry, or skip each file
|
@@ -208,19 +211,44 @@ You can use interactive mode with `--dry-run` to preview without actually renami
|
|
208
211
|
|
209
212
|
## How It Works
|
210
213
|
|
211
|
-
|
212
|
-
|
213
|
-
|
214
|
-
|
215
|
-
|
216
|
-
|
217
|
-
|
218
|
-
|
214
|
+
### Intelligent Hybrid Approach
|
215
|
+
|
216
|
+
The tool uses a multi-strategy approach to generate accurate filenames:
|
217
|
+
|
218
|
+
1. **DOI Detection** (for academic papers)
|
219
|
+
- Searches PDF for DOI identifiers using [pdf2doi](https://github.com/MicheleCotrufo/pdf2doi)
|
220
|
+
- If found, queries authoritative metadata (title, authors, year, journal)
|
221
|
+
- Generates filename with **very high confidence** from validated metadata
|
222
|
+
- **Saves API costs** - no LLM call needed for papers with DOIs
|
223
|
+
|
224
|
+
2. **LLM Analysis** (fallback for non-academic PDFs)
|
225
|
+
- **Extract**: Uses docling-parse to read first 5 pages with structure-aware parsing, falls back to PyMuPDF if needed
|
226
|
+
- **OCR**: Automatically applies OCR for scanned PDFs with minimal text
|
227
|
+
- **Metadata Enhancement**: Extracts focused hints (years, emails, author sections) to supplement unreliable PDF metadata
|
228
|
+
- **Analyze**: Sends full content excerpt to LLM with enhanced metadata and detailed extraction instructions
|
229
|
+
- **Multi-pass Review**: Low-confidence results trigger a second analysis pass with focused prompts
|
230
|
+
- **Suggest**: LLM returns filename in `Author-Topic-Year` format with confidence level and reasoning
|
231
|
+
|
232
|
+
3. **Interactive Review** (optional): User can accept, edit, retry, or skip each suggestion
|
233
|
+
4. **Rename**: Applies suggestions (if not in dry-run mode)
|
234
|
+
|
235
|
+
### Benefits of DOI Integration
|
236
|
+
|
237
|
+
- **Accuracy**: DOI metadata is canonical and verified
|
238
|
+
- **Speed**: Instant lookup vs. LLM processing time
|
239
|
+
- **Cost**: Free DOI lookups save on API costs for academic papers
|
240
|
+
- **Reliability**: Works even when PDF text extraction is poor
|
219
241
|
|
220
242
|
## Cost Considerations
|
221
243
|
|
222
|
-
**
|
244
|
+
**DOI-based Naming (Academic Papers):**
|
245
|
+
- **Completely free** - No API costs
|
246
|
+
- **No LLM needed** - Direct metadata lookup
|
247
|
+
- Works for most academic papers with embedded DOIs
|
248
|
+
|
249
|
+
**OpenAI (Fallback):**
|
223
250
|
- Uses `gpt-4o-mini` by default (very cost-effective)
|
251
|
+
- Only called when DOI not found
|
224
252
|
- Processes first ~4500 characters per PDF
|
225
253
|
- Typical cost: ~$0.001-0.003 per PDF
|
226
254
|
|
@@ -18,9 +18,11 @@ Intelligent PDF file renaming using LLMs. This tool analyzes PDF content and met
|
|
18
18
|
|
19
19
|
## Features
|
20
20
|
|
21
|
+
- **DOI-based naming** - Automatically extracts DOI and fetches authoritative metadata for academic papers
|
21
22
|
- **Advanced PDF parsing** using docling-parse for better structure-aware extraction
|
22
23
|
- **OCR fallback** for scanned PDFs with low text content
|
23
24
|
- **Smart LLM prompting** with multi-pass analysis for improved accuracy
|
25
|
+
- **Hybrid approach** - Uses DOI metadata when available, falls back to LLM analysis for other documents
|
24
26
|
- Suggests filenames in format: `Author-Topic-Year.pdf`
|
25
27
|
- Dry-run mode to preview changes before applying
|
26
28
|
- **Enhanced interactive mode** with options to accept, manually edit, retry, or skip each file
|
@@ -183,19 +185,44 @@ You can use interactive mode with `--dry-run` to preview without actually renami
|
|
183
185
|
|
184
186
|
## How It Works
|
185
187
|
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
188
|
+
### Intelligent Hybrid Approach
|
189
|
+
|
190
|
+
The tool uses a multi-strategy approach to generate accurate filenames:
|
191
|
+
|
192
|
+
1. **DOI Detection** (for academic papers)
|
193
|
+
- Searches PDF for DOI identifiers using [pdf2doi](https://github.com/MicheleCotrufo/pdf2doi)
|
194
|
+
- If found, queries authoritative metadata (title, authors, year, journal)
|
195
|
+
- Generates filename with **very high confidence** from validated metadata
|
196
|
+
- **Saves API costs** - no LLM call needed for papers with DOIs
|
197
|
+
|
198
|
+
2. **LLM Analysis** (fallback for non-academic PDFs)
|
199
|
+
- **Extract**: Uses docling-parse to read first 5 pages with structure-aware parsing, falls back to PyMuPDF if needed
|
200
|
+
- **OCR**: Automatically applies OCR for scanned PDFs with minimal text
|
201
|
+
- **Metadata Enhancement**: Extracts focused hints (years, emails, author sections) to supplement unreliable PDF metadata
|
202
|
+
- **Analyze**: Sends full content excerpt to LLM with enhanced metadata and detailed extraction instructions
|
203
|
+
- **Multi-pass Review**: Low-confidence results trigger a second analysis pass with focused prompts
|
204
|
+
- **Suggest**: LLM returns filename in `Author-Topic-Year` format with confidence level and reasoning
|
205
|
+
|
206
|
+
3. **Interactive Review** (optional): User can accept, edit, retry, or skip each suggestion
|
207
|
+
4. **Rename**: Applies suggestions (if not in dry-run mode)
|
208
|
+
|
209
|
+
### Benefits of DOI Integration
|
210
|
+
|
211
|
+
- **Accuracy**: DOI metadata is canonical and verified
|
212
|
+
- **Speed**: Instant lookup vs. LLM processing time
|
213
|
+
- **Cost**: Free DOI lookups save on API costs for academic papers
|
214
|
+
- **Reliability**: Works even when PDF text extraction is poor
|
194
215
|
|
195
216
|
## Cost Considerations
|
196
217
|
|
197
|
-
**
|
218
|
+
**DOI-based Naming (Academic Papers):**
|
219
|
+
- **Completely free** - No API costs
|
220
|
+
- **No LLM needed** - Direct metadata lookup
|
221
|
+
- Works for most academic papers with embedded DOIs
|
222
|
+
|
223
|
+
**OpenAI (Fallback):**
|
198
224
|
- Uses `gpt-4o-mini` by default (very cost-effective)
|
225
|
+
- Only called when DOI not found
|
199
226
|
- Processes first ~4500 characters per PDF
|
200
227
|
- Typical cost: ~$0.001-0.003 per PDF
|
201
228
|
|
@@ -1,5 +1,5 @@
|
|
1
1
|
<?xml version="1.0" ?>
|
2
|
-
<coverage version="7.10.7" timestamp="
|
2
|
+
<coverage version="7.10.7" timestamp="1760461998034" lines-valid="702" lines-covered="142" line-rate="0.2023" branches-covered="0" branches-valid="0" branch-rate="0" complexity="0">
|
3
3
|
<!-- Generated by coverage.py: https://coverage.readthedocs.io/en/7.10.7 -->
|
4
4
|
<!-- Based on https://raw.githubusercontent.com/cobertura/web/master/htdocs/xml/coverage-04.dtd -->
|
5
5
|
<sources>
|
@@ -22,7 +22,7 @@
|
|
22
22
|
</class>
|
23
23
|
</classes>
|
24
24
|
</package>
|
25
|
-
<package name="src.pdf_file_renamer.application" line-rate="0.
|
25
|
+
<package name="src.pdf_file_renamer.application" line-rate="0.5194" branch-rate="0" complexity="0">
|
26
26
|
<classes>
|
27
27
|
<class name="__init__.py" filename="src/pdf_file_renamer/application/__init__.py" complexity="0" line-rate="1" branch-rate="0">
|
28
28
|
<methods/>
|
@@ -33,7 +33,7 @@
|
|
33
33
|
<line number="7" hits="1"/>
|
34
34
|
</lines>
|
35
35
|
</class>
|
36
|
-
<class name="filename_service.py" filename="src/pdf_file_renamer/application/filename_service.py" complexity="0" line-rate="
|
36
|
+
<class name="filename_service.py" filename="src/pdf_file_renamer/application/filename_service.py" complexity="0" line-rate="0.4773" branch-rate="0">
|
37
37
|
<methods/>
|
38
38
|
<lines>
|
39
39
|
<line number="3" hits="1"/>
|
@@ -44,57 +44,96 @@
|
|
44
44
|
<line number="19" hits="1"/>
|
45
45
|
<line number="21" hits="1"/>
|
46
46
|
<line number="33" hits="1"/>
|
47
|
-
<line number="
|
48
|
-
<line number="
|
49
|
-
<line number="
|
50
|
-
<line number="
|
51
|
-
<line number="
|
52
|
-
<line number="
|
53
|
-
<line number="
|
54
|
-
<line number="
|
55
|
-
<line number="
|
56
|
-
<line number="
|
47
|
+
<line number="34" hits="0"/>
|
48
|
+
<line number="38" hits="1"/>
|
49
|
+
<line number="41" hits="1"/>
|
50
|
+
<line number="48" hits="1"/>
|
51
|
+
<line number="50" hits="1"/>
|
52
|
+
<line number="52" hits="1"/>
|
53
|
+
<line number="62" hits="0"/>
|
54
|
+
<line number="63" hits="0"/>
|
55
|
+
<line number="64" hits="0"/>
|
56
|
+
<line number="65" hits="0"/>
|
57
|
+
<line number="68" hits="0"/>
|
58
|
+
<line number="71" hits="0"/>
|
59
|
+
<line number="73" hits="0"/>
|
60
|
+
<line number="75" hits="0"/>
|
61
|
+
<line number="78" hits="0"/>
|
62
|
+
<line number="79" hits="0"/>
|
63
|
+
<line number="80" hits="0"/>
|
64
|
+
<line number="81" hits="0"/>
|
65
|
+
<line number="82" hits="0"/>
|
66
|
+
<line number="84" hits="0"/>
|
67
|
+
<line number="85" hits="0"/>
|
68
|
+
<line number="87" hits="0"/>
|
69
|
+
<line number="94" hits="1"/>
|
70
|
+
<line number="106" hits="0"/>
|
71
|
+
<line number="136" hits="0"/>
|
72
|
+
<line number="139" hits="0"/>
|
73
|
+
<line number="142" hits="0"/>
|
74
|
+
<line number="145" hits="0"/>
|
75
|
+
<line number="147" hits="0"/>
|
76
|
+
<line number="149" hits="1"/>
|
77
|
+
<line number="160" hits="1"/>
|
78
|
+
<line number="163" hits="1"/>
|
79
|
+
<line number="166" hits="1"/>
|
80
|
+
<line number="169" hits="1"/>
|
81
|
+
<line number="170" hits="1"/>
|
82
|
+
<line number="172" hits="1"/>
|
57
83
|
</lines>
|
58
84
|
</class>
|
59
|
-
<class name="pdf_rename_workflow.py" filename="src/pdf_file_renamer/application/pdf_rename_workflow.py" complexity="0" line-rate="0.
|
85
|
+
<class name="pdf_rename_workflow.py" filename="src/pdf_file_renamer/application/pdf_rename_workflow.py" complexity="0" line-rate="0.2245" branch-rate="0">
|
60
86
|
<methods/>
|
61
87
|
<lines>
|
62
88
|
<line number="3" hits="1"/>
|
63
89
|
<line number="4" hits="1"/>
|
64
90
|
<line number="5" hits="1"/>
|
65
|
-
<line number="
|
91
|
+
<line number="6" hits="1"/>
|
66
92
|
<line number="8" hits="1"/>
|
67
|
-
<line number="
|
68
|
-
<line number="
|
69
|
-
<line number="
|
70
|
-
<line number="42" hits="0"/>
|
71
|
-
<line number="43" hits="0"/>
|
72
|
-
<line number="44" hits="0"/>
|
93
|
+
<line number="9" hits="1"/>
|
94
|
+
<line number="17" hits="1"/>
|
95
|
+
<line number="25" hits="1"/>
|
73
96
|
<line number="45" hits="0"/>
|
74
|
-
<line number="
|
75
|
-
<line number="
|
76
|
-
<line number="
|
77
|
-
<line number="
|
97
|
+
<line number="46" hits="0"/>
|
98
|
+
<line number="47" hits="0"/>
|
99
|
+
<line number="48" hits="0"/>
|
100
|
+
<line number="49" hits="0"/>
|
101
|
+
<line number="50" hits="0"/>
|
102
|
+
<line number="52" hits="1"/>
|
78
103
|
<line number="67" hits="0"/>
|
79
|
-
<line number="
|
104
|
+
<line number="69" hits="0"/>
|
80
105
|
<line number="71" hits="0"/>
|
106
|
+
<line number="72" hits="0"/>
|
107
|
+
<line number="73" hits="0"/>
|
81
108
|
<line number="74" hits="0"/>
|
82
|
-
<line number="75" hits="0"/>
|
83
109
|
<line number="77" hits="0"/>
|
84
110
|
<line number="78" hits="0"/>
|
85
111
|
<line number="81" hits="0"/>
|
86
112
|
<line number="82" hits="0"/>
|
87
|
-
<line number="
|
88
|
-
<line number="
|
113
|
+
<line number="83" hits="0"/>
|
114
|
+
<line number="86" hits="0"/>
|
115
|
+
<line number="87" hits="0"/>
|
116
|
+
<line number="90" hits="0"/>
|
117
|
+
<line number="92" hits="0"/>
|
118
|
+
<line number="94" hits="0"/>
|
119
|
+
<line number="97" hits="0"/>
|
120
|
+
<line number="98" hits="0"/>
|
121
|
+
<line number="99" hits="0"/>
|
89
122
|
<line number="101" hits="0"/>
|
90
123
|
<line number="102" hits="0"/>
|
91
|
-
<line number="
|
92
|
-
<line number="
|
93
|
-
<line number="
|
94
|
-
<line number="
|
95
|
-
<line number="
|
96
|
-
<line number="
|
97
|
-
<line number="
|
124
|
+
<line number="105" hits="0"/>
|
125
|
+
<line number="106" hits="0"/>
|
126
|
+
<line number="115" hits="0"/>
|
127
|
+
<line number="125" hits="0"/>
|
128
|
+
<line number="126" hits="0"/>
|
129
|
+
<line number="127" hits="0"/>
|
130
|
+
<line number="128" hits="0"/>
|
131
|
+
<line number="130" hits="1"/>
|
132
|
+
<line number="145" hits="0"/>
|
133
|
+
<line number="146" hits="0"/>
|
134
|
+
<line number="148" hits="1"/>
|
135
|
+
<line number="168" hits="0"/>
|
136
|
+
<line number="169" hits="0"/>
|
98
137
|
</lines>
|
99
138
|
</class>
|
100
139
|
<class name="rename_service.py" filename="src/pdf_file_renamer/application/rename_service.py" complexity="0" line-rate="0.9688" branch-rate="0">
|
@@ -136,7 +175,7 @@
|
|
136
175
|
</class>
|
137
176
|
</classes>
|
138
177
|
</package>
|
139
|
-
<package name="src.pdf_file_renamer.domain" line-rate="
|
178
|
+
<package name="src.pdf_file_renamer.domain" line-rate="0.9136" branch-rate="0" complexity="0">
|
140
179
|
<classes>
|
141
180
|
<class name="__init__.py" filename="src/pdf_file_renamer/domain/__init__.py" complexity="0" line-rate="1" branch-rate="0">
|
142
181
|
<methods/>
|
@@ -146,7 +185,7 @@
|
|
146
185
|
<line number="16" hits="1"/>
|
147
186
|
</lines>
|
148
187
|
</class>
|
149
|
-
<class name="models.py" filename="src/pdf_file_renamer/domain/models.py" complexity="0" line-rate="
|
188
|
+
<class name="models.py" filename="src/pdf_file_renamer/domain/models.py" complexity="0" line-rate="0.9" branch-rate="0">
|
150
189
|
<methods/>
|
151
190
|
<lines>
|
152
191
|
<line number="3" hits="1"/>
|
@@ -158,46 +197,67 @@
|
|
158
197
|
<line number="14" hits="1"/>
|
159
198
|
<line number="15" hits="1"/>
|
160
199
|
<line number="16" hits="1"/>
|
161
|
-
<line number="
|
162
|
-
<line number="
|
200
|
+
<line number="17" hits="1"/>
|
201
|
+
<line number="20" hits="1"/>
|
202
|
+
<line number="21" hits="1"/>
|
163
203
|
<line number="24" hits="1"/>
|
164
204
|
<line number="25" hits="1"/>
|
165
205
|
<line number="26" hits="1"/>
|
206
|
+
<line number="27" hits="1"/>
|
207
|
+
<line number="28" hits="1"/>
|
166
208
|
<line number="29" hits="1"/>
|
167
209
|
<line number="30" hits="1"/>
|
210
|
+
<line number="32" hits="1"/>
|
168
211
|
<line number="33" hits="1"/>
|
169
|
-
<line number="
|
170
|
-
<line number="
|
171
|
-
<line number="
|
172
|
-
<line number="
|
173
|
-
<line number="
|
174
|
-
<line number="
|
175
|
-
<line number="
|
176
|
-
<line number="
|
177
|
-
<line number="43" hits="1"/>
|
178
|
-
<line number="44" hits="1"/>
|
179
|
-
<line number="45" hits="1"/>
|
180
|
-
<line number="47" hits="1"/>
|
212
|
+
<line number="35" hits="0"/>
|
213
|
+
<line number="36" hits="0"/>
|
214
|
+
<line number="38" hits="0"/>
|
215
|
+
<line number="39" hits="0"/>
|
216
|
+
<line number="40" hits="0"/>
|
217
|
+
<line number="42" hits="0"/>
|
218
|
+
<line number="43" hits="0"/>
|
219
|
+
<line number="46" hits="1"/>
|
181
220
|
<line number="49" hits="1"/>
|
221
|
+
<line number="51" hits="1"/>
|
182
222
|
<line number="52" hits="1"/>
|
183
223
|
<line number="53" hits="1"/>
|
184
224
|
<line number="56" hits="1"/>
|
185
225
|
<line number="57" hits="1"/>
|
186
|
-
<line number="
|
226
|
+
<line number="60" hits="1"/>
|
187
227
|
<line number="61" hits="1"/>
|
188
228
|
<line number="62" hits="1"/>
|
229
|
+
<line number="63" hits="1"/>
|
230
|
+
<line number="64" hits="1"/>
|
189
231
|
<line number="65" hits="1"/>
|
190
232
|
<line number="66" hits="1"/>
|
191
233
|
<line number="67" hits="1"/>
|
192
|
-
<line number="68" hits="1"/>
|
193
234
|
<line number="69" hits="1"/>
|
194
235
|
<line number="70" hits="1"/>
|
236
|
+
<line number="71" hits="1"/>
|
195
237
|
<line number="72" hits="1"/>
|
196
|
-
<line number="
|
197
|
-
<line number="
|
198
|
-
<line number="77" hits="1"/>
|
238
|
+
<line number="74" hits="1"/>
|
239
|
+
<line number="76" hits="1"/>
|
199
240
|
<line number="79" hits="1"/>
|
200
241
|
<line number="80" hits="1"/>
|
242
|
+
<line number="83" hits="1"/>
|
243
|
+
<line number="84" hits="1"/>
|
244
|
+
<line number="85" hits="1"/>
|
245
|
+
<line number="86" hits="1"/>
|
246
|
+
<line number="89" hits="1"/>
|
247
|
+
<line number="90" hits="1"/>
|
248
|
+
<line number="93" hits="1"/>
|
249
|
+
<line number="94" hits="1"/>
|
250
|
+
<line number="95" hits="1"/>
|
251
|
+
<line number="96" hits="1"/>
|
252
|
+
<line number="97" hits="1"/>
|
253
|
+
<line number="98" hits="1"/>
|
254
|
+
<line number="99" hits="1"/>
|
255
|
+
<line number="101" hits="1"/>
|
256
|
+
<line number="102" hits="1"/>
|
257
|
+
<line number="104" hits="1"/>
|
258
|
+
<line number="106" hits="1"/>
|
259
|
+
<line number="108" hits="1"/>
|
260
|
+
<line number="109" hits="1"/>
|
201
261
|
</lines>
|
202
262
|
</class>
|
203
263
|
<class name="ports.py" filename="src/pdf_file_renamer/domain/ports.py" complexity="0" line-rate="1" branch-rate="0">
|
@@ -207,9 +267,10 @@
|
|
207
267
|
<line number="4" hits="1"/>
|
208
268
|
<line number="6" hits="1"/>
|
209
269
|
<line number="9" hits="1"/>
|
210
|
-
<line number="
|
211
|
-
<line number="
|
212
|
-
<line number="
|
270
|
+
<line number="26" hits="1"/>
|
271
|
+
<line number="46" hits="1"/>
|
272
|
+
<line number="73" hits="1"/>
|
273
|
+
<line number="104" hits="1"/>
|
213
274
|
</lines>
|
214
275
|
</class>
|
215
276
|
</classes>
|
@@ -251,6 +312,71 @@
|
|
251
312
|
</class>
|
252
313
|
</classes>
|
253
314
|
</package>
|
315
|
+
<package name="src.pdf_file_renamer.infrastructure.doi" line-rate="0" branch-rate="0" complexity="0">
|
316
|
+
<classes>
|
317
|
+
<class name="__init__.py" filename="src/pdf_file_renamer/infrastructure/doi/__init__.py" complexity="0" line-rate="0" branch-rate="0">
|
318
|
+
<methods/>
|
319
|
+
<lines>
|
320
|
+
<line number="3" hits="0"/>
|
321
|
+
<line number="5" hits="0"/>
|
322
|
+
</lines>
|
323
|
+
</class>
|
324
|
+
<class name="pdf2doi_extractor.py" filename="src/pdf_file_renamer/infrastructure/doi/pdf2doi_extractor.py" complexity="0" line-rate="0" branch-rate="0">
|
325
|
+
<methods/>
|
326
|
+
<lines>
|
327
|
+
<line number="3" hits="0"/>
|
328
|
+
<line number="4" hits="0"/>
|
329
|
+
<line number="5" hits="0"/>
|
330
|
+
<line number="7" hits="0"/>
|
331
|
+
<line number="9" hits="0"/>
|
332
|
+
<line number="10" hits="0"/>
|
333
|
+
<line number="13" hits="0"/>
|
334
|
+
<line number="16" hits="0"/>
|
335
|
+
<line number="19" hits="0"/>
|
336
|
+
<line number="21" hits="0"/>
|
337
|
+
<line number="31" hits="0"/>
|
338
|
+
<line number="33" hits="0"/>
|
339
|
+
<line number="34" hits="0"/>
|
340
|
+
<line number="38" hits="0"/>
|
341
|
+
<line number="39" hits="0"/>
|
342
|
+
<line number="42" hits="0"/>
|
343
|
+
<line number="45" hits="0"/>
|
344
|
+
<line number="46" hits="0"/>
|
345
|
+
<line number="47" hits="0"/>
|
346
|
+
<line number="49" hits="0"/>
|
347
|
+
<line number="50" hits="0"/>
|
348
|
+
<line number="51" hits="0"/>
|
349
|
+
<line number="54" hits="0"/>
|
350
|
+
<line number="57" hits="0"/>
|
351
|
+
<line number="58" hits="0"/>
|
352
|
+
<line number="59" hits="0"/>
|
353
|
+
<line number="60" hits="0"/>
|
354
|
+
<line number="61" hits="0"/>
|
355
|
+
<line number="63" hits="0"/>
|
356
|
+
<line number="73" hits="0"/>
|
357
|
+
<line number="75" hits="0"/>
|
358
|
+
<line number="77" hits="0"/>
|
359
|
+
<line number="88" hits="0"/>
|
360
|
+
<line number="89" hits="0"/>
|
361
|
+
<line number="92" hits="0"/>
|
362
|
+
<line number="93" hits="0"/>
|
363
|
+
<line number="95" hits="0"/>
|
364
|
+
<line number="96" hits="0"/>
|
365
|
+
<line number="98" hits="0"/>
|
366
|
+
<line number="100" hits="0"/>
|
367
|
+
<line number="110" hits="0"/>
|
368
|
+
<line number="111" hits="0"/>
|
369
|
+
<line number="114" hits="0"/>
|
370
|
+
<line number="115" hits="0"/>
|
371
|
+
<line number="117" hits="0"/>
|
372
|
+
<line number="118" hits="0"/>
|
373
|
+
<line number="120" hits="0"/>
|
374
|
+
<line number="123" hits="0"/>
|
375
|
+
<line number="129" hits="0"/>
|
376
|
+
</lines>
|
377
|
+
</class>
|
378
|
+
</classes>
|
379
|
+
</package>
|
254
380
|
<package name="src.pdf_file_renamer.infrastructure.llm" line-rate="0" branch-rate="0" complexity="0">
|
255
381
|
<classes>
|
256
382
|
<class name="__init__.py" filename="src/pdf_file_renamer/infrastructure/llm/__init__.py" complexity="0" line-rate="0" branch-rate="0">
|
@@ -518,88 +644,90 @@
|
|
518
644
|
<line number="17" hits="0"/>
|
519
645
|
<line number="18" hits="0"/>
|
520
646
|
<line number="19" hits="0"/>
|
521
|
-
<line number="
|
522
|
-
<line number="
|
647
|
+
<line number="20" hits="0"/>
|
648
|
+
<line number="25" hits="0"/>
|
523
649
|
<line number="31" hits="0"/>
|
524
|
-
<line number="
|
525
|
-
<line number="
|
526
|
-
<line number="
|
527
|
-
<line number="
|
528
|
-
<line number="
|
650
|
+
<line number="32" hits="0"/>
|
651
|
+
<line number="35" hits="0"/>
|
652
|
+
<line number="48" hits="0"/>
|
653
|
+
<line number="56" hits="0"/>
|
654
|
+
<line number="59" hits="0"/>
|
529
655
|
<line number="69" hits="0"/>
|
530
656
|
<line number="72" hits="0"/>
|
531
|
-
<line number="
|
532
|
-
<line number="
|
533
|
-
<line number="
|
534
|
-
<line number="
|
535
|
-
<line number="112" hits="0"/>
|
657
|
+
<line number="73" hits="0"/>
|
658
|
+
<line number="76" hits="0"/>
|
659
|
+
<line number="86" hits="0"/>
|
660
|
+
<line number="87" hits="0"/>
|
536
661
|
<line number="113" hits="0"/>
|
537
|
-
<line number="
|
662
|
+
<line number="116" hits="0"/>
|
538
663
|
<line number="117" hits="0"/>
|
539
664
|
<line number="118" hits="0"/>
|
540
665
|
<line number="119" hits="0"/>
|
541
|
-
<line number="
|
542
|
-
<line number="
|
666
|
+
<line number="122" hits="0"/>
|
667
|
+
<line number="123" hits="0"/>
|
543
668
|
<line number="124" hits="0"/>
|
544
669
|
<line number="125" hits="0"/>
|
545
670
|
<line number="126" hits="0"/>
|
546
|
-
<line number="127" hits="0"/>
|
547
671
|
<line number="129" hits="0"/>
|
672
|
+
<line number="130" hits="0"/>
|
673
|
+
<line number="131" hits="0"/>
|
548
674
|
<line number="132" hits="0"/>
|
549
|
-
<line number="
|
550
|
-
<line number="
|
551
|
-
<line number="
|
552
|
-
<line number="
|
553
|
-
<line number="
|
675
|
+
<line number="134" hits="0"/>
|
676
|
+
<line number="137" hits="0"/>
|
677
|
+
<line number="140" hits="0"/>
|
678
|
+
<line number="141" hits="0"/>
|
679
|
+
<line number="143" hits="0"/>
|
554
680
|
<line number="144" hits="0"/>
|
555
|
-
<line number="145" hits="0"/>
|
556
|
-
<line number="146" hits="0"/>
|
557
681
|
<line number="147" hits="0"/>
|
558
682
|
<line number="149" hits="0"/>
|
683
|
+
<line number="150" hits="0"/>
|
559
684
|
<line number="151" hits="0"/>
|
560
|
-
<line number="
|
685
|
+
<line number="152" hits="0"/>
|
561
686
|
<line number="154" hits="0"/>
|
562
|
-
<line number="
|
563
|
-
<line number="
|
687
|
+
<line number="156" hits="0"/>
|
688
|
+
<line number="158" hits="0"/>
|
564
689
|
<line number="159" hits="0"/>
|
690
|
+
<line number="160" hits="0"/>
|
565
691
|
<line number="162" hits="0"/>
|
566
|
-
<line number="
|
567
|
-
<line number="
|
692
|
+
<line number="164" hits="0"/>
|
693
|
+
<line number="167" hits="0"/>
|
568
694
|
<line number="171" hits="0"/>
|
569
|
-
<line number="
|
570
|
-
<line number="173" hits="0"/>
|
695
|
+
<line number="174" hits="0"/>
|
571
696
|
<line number="176" hits="0"/>
|
572
697
|
<line number="177" hits="0"/>
|
573
|
-
<line number="
|
698
|
+
<line number="178" hits="0"/>
|
574
699
|
<line number="181" hits="0"/>
|
575
700
|
<line number="182" hits="0"/>
|
576
|
-
<line number="
|
701
|
+
<line number="185" hits="0"/>
|
702
|
+
<line number="186" hits="0"/>
|
577
703
|
<line number="187" hits="0"/>
|
578
704
|
<line number="189" hits="0"/>
|
579
|
-
<line number="191" hits="0"/>
|
580
705
|
<line number="192" hits="0"/>
|
581
|
-
<line number="193" hits="0"/>
|
582
706
|
<line number="194" hits="0"/>
|
583
|
-
<line number="
|
707
|
+
<line number="196" hits="0"/>
|
584
708
|
<line number="197" hits="0"/>
|
709
|
+
<line number="198" hits="0"/>
|
710
|
+
<line number="199" hits="0"/>
|
585
711
|
<line number="200" hits="0"/>
|
586
|
-
<line number="201" hits="0"/>
|
587
712
|
<line number="202" hits="0"/>
|
588
713
|
<line number="205" hits="0"/>
|
589
714
|
<line number="206" hits="0"/>
|
590
715
|
<line number="207" hits="0"/>
|
591
|
-
<line number="
|
592
|
-
<line number="
|
716
|
+
<line number="210" hits="0"/>
|
717
|
+
<line number="211" hits="0"/>
|
718
|
+
<line number="212" hits="0"/>
|
719
|
+
<line number="213" hits="0"/>
|
593
720
|
<line number="214" hits="0"/>
|
594
|
-
<line number="215" hits="0"/>
|
595
|
-
<line number="218" hits="0"/>
|
596
721
|
<line number="219" hits="0"/>
|
597
722
|
<line number="220" hits="0"/>
|
598
723
|
<line number="223" hits="0"/>
|
724
|
+
<line number="224" hits="0"/>
|
599
725
|
<line number="225" hits="0"/>
|
600
|
-
<line number="226" hits="0"/>
|
601
726
|
<line number="228" hits="0"/>
|
602
|
-
<line number="
|
727
|
+
<line number="230" hits="0"/>
|
728
|
+
<line number="231" hits="0"/>
|
729
|
+
<line number="233" hits="0"/>
|
730
|
+
<line number="234" hits="0"/>
|
603
731
|
</lines>
|
604
732
|
</class>
|
605
733
|
<class name="formatters.py" filename="src/pdf_file_renamer/presentation/formatters.py" complexity="0" line-rate="0" branch-rate="0">
|