pdf-file-renamer 0.6.0__tar.gz → 0.6.1__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.6.0 → pdf_file_renamer-0.6.1}/PKG-INFO +1 -1
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/coverage.xml +76 -49
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/pyproject.toml +1 -1
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/__init__.py +1 -1
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/application/pdf_rename_workflow.py +8 -2
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/doi/pdf2doi_extractor.py +46 -12
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/presentation/formatters.py +15 -3
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/.env.example +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/.github/workflows/ci.yml +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/.github/workflows/release.yml +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/.gitignore +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/.python-version +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/LICENSE +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/README.md +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/REFACTORING_SUMMARY.md +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/application/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/application/filename_service.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/application/rename_service.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/domain/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/domain/models.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/domain/ports.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/config.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/doi/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/llm/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/llm/pydantic_ai_provider.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/pdf/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/pdf/composite.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/pdf/docling_extractor.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/pdf/pymupdf_extractor.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/main.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/presentation/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/presentation/cli.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/__init__.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/data/2025-dennis-managing-complexity.pdf +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/data/Camp_of_the_Saints.pdf +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/data/s43588-025-00854-1.pdf +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/test_domain_models.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/test_filename_service.py +0 -0
- {pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/test_rename_service.py +0 -0
@@ -1,5 +1,5 @@
|
|
1
1
|
<?xml version="1.0" ?>
|
2
|
-
<coverage version="7.10.7" timestamp="
|
2
|
+
<coverage version="7.10.7" timestamp="1760480007723" lines-valid="729" lines-covered="142" line-rate="0.1948" 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.5154" 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/>
|
@@ -82,7 +82,7 @@
|
|
82
82
|
<line number="172" hits="1"/>
|
83
83
|
</lines>
|
84
84
|
</class>
|
85
|
-
<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.22" branch-rate="0">
|
86
86
|
<methods/>
|
87
87
|
<lines>
|
88
88
|
<line number="3" hits="1"/>
|
@@ -122,18 +122,19 @@
|
|
122
122
|
<line number="101" hits="0"/>
|
123
123
|
<line number="102" hits="0"/>
|
124
124
|
<line number="105" hits="0"/>
|
125
|
-
<line number="
|
126
|
-
<line number="
|
127
|
-
<line number="
|
128
|
-
<line number="
|
129
|
-
<line number="
|
130
|
-
<line number="
|
131
|
-
<line number="
|
132
|
-
<line number="
|
133
|
-
<line number="
|
134
|
-
<line number="
|
135
|
-
<line number="
|
136
|
-
<line number="
|
125
|
+
<line number="107" hits="0"/>
|
126
|
+
<line number="112" hits="0"/>
|
127
|
+
<line number="121" hits="0"/>
|
128
|
+
<line number="131" hits="0"/>
|
129
|
+
<line number="132" hits="0"/>
|
130
|
+
<line number="133" hits="0"/>
|
131
|
+
<line number="134" hits="0"/>
|
132
|
+
<line number="136" hits="1"/>
|
133
|
+
<line number="151" hits="0"/>
|
134
|
+
<line number="152" hits="0"/>
|
135
|
+
<line number="154" hits="1"/>
|
136
|
+
<line number="174" hits="0"/>
|
137
|
+
<line number="175" hits="0"/>
|
137
138
|
</lines>
|
138
139
|
</class>
|
139
140
|
<class name="rename_service.py" filename="src/pdf_file_renamer/application/rename_service.py" complexity="0" line-rate="0.9688" branch-rate="0">
|
@@ -337,42 +338,66 @@
|
|
337
338
|
<line number="31" hits="0"/>
|
338
339
|
<line number="33" hits="0"/>
|
339
340
|
<line number="34" hits="0"/>
|
340
|
-
<line number="38" hits="0"/>
|
341
341
|
<line number="39" hits="0"/>
|
342
|
-
<line number="
|
342
|
+
<line number="40" hits="0"/>
|
343
|
+
<line number="43" hits="0"/>
|
344
|
+
<line number="44" hits="0"/>
|
343
345
|
<line number="45" hits="0"/>
|
344
|
-
<line number="46" hits="0"/>
|
345
346
|
<line number="47" hits="0"/>
|
347
|
+
<line number="48" hits="0"/>
|
346
348
|
<line number="49" hits="0"/>
|
347
|
-
<line number="
|
348
|
-
<line number="
|
349
|
-
<line number="54" hits="0"/>
|
349
|
+
<line number="52" hits="0"/>
|
350
|
+
<line number="55" hits="0"/>
|
350
351
|
<line number="57" hits="0"/>
|
351
352
|
<line number="58" hits="0"/>
|
352
353
|
<line number="59" hits="0"/>
|
353
354
|
<line number="60" hits="0"/>
|
354
355
|
<line number="61" hits="0"/>
|
355
|
-
<line number="
|
356
|
+
<line number="62" hits="0"/>
|
357
|
+
<line number="65" hits="0"/>
|
358
|
+
<line number="68" hits="0"/>
|
359
|
+
<line number="69" hits="0"/>
|
360
|
+
<line number="70" hits="0"/>
|
361
|
+
<line number="71" hits="0"/>
|
362
|
+
<line number="72" hits="0"/>
|
356
363
|
<line number="73" hits="0"/>
|
364
|
+
<line number="74" hits="0"/>
|
357
365
|
<line number="75" hits="0"/>
|
366
|
+
<line number="76" hits="0"/>
|
358
367
|
<line number="77" hits="0"/>
|
368
|
+
<line number="78" hits="0"/>
|
369
|
+
<line number="79" hits="0"/>
|
370
|
+
<line number="80" hits="0"/>
|
371
|
+
<line number="83" hits="0"/>
|
372
|
+
<line number="84" hits="0"/>
|
373
|
+
<line number="85" hits="0"/>
|
374
|
+
<line number="86" hits="0"/>
|
375
|
+
<line number="87" hits="0"/>
|
359
376
|
<line number="88" hits="0"/>
|
360
377
|
<line number="89" hits="0"/>
|
361
378
|
<line number="92" hits="0"/>
|
362
|
-
<line number="93" hits="0"/>
|
363
379
|
<line number="95" hits="0"/>
|
364
|
-
<line number="
|
365
|
-
<line number="
|
366
|
-
<line number="
|
367
|
-
<line number="110" hits="0"/>
|
380
|
+
<line number="97" hits="0"/>
|
381
|
+
<line number="107" hits="0"/>
|
382
|
+
<line number="109" hits="0"/>
|
368
383
|
<line number="111" hits="0"/>
|
369
|
-
<line number="
|
370
|
-
<line number="115" hits="0"/>
|
371
|
-
<line number="117" hits="0"/>
|
372
|
-
<line number="118" hits="0"/>
|
373
|
-
<line number="120" hits="0"/>
|
384
|
+
<line number="122" hits="0"/>
|
374
385
|
<line number="123" hits="0"/>
|
386
|
+
<line number="126" hits="0"/>
|
387
|
+
<line number="127" hits="0"/>
|
375
388
|
<line number="129" hits="0"/>
|
389
|
+
<line number="130" hits="0"/>
|
390
|
+
<line number="132" hits="0"/>
|
391
|
+
<line number="134" hits="0"/>
|
392
|
+
<line number="144" hits="0"/>
|
393
|
+
<line number="145" hits="0"/>
|
394
|
+
<line number="148" hits="0"/>
|
395
|
+
<line number="149" hits="0"/>
|
396
|
+
<line number="151" hits="0"/>
|
397
|
+
<line number="152" hits="0"/>
|
398
|
+
<line number="154" hits="0"/>
|
399
|
+
<line number="157" hits="0"/>
|
400
|
+
<line number="163" hits="0"/>
|
376
401
|
</lines>
|
377
402
|
</class>
|
378
403
|
</classes>
|
@@ -810,34 +835,30 @@
|
|
810
835
|
<line number="146" hits="0"/>
|
811
836
|
<line number="147" hits="0"/>
|
812
837
|
<line number="148" hits="0"/>
|
813
|
-
<line number="149" hits="0"/>
|
814
838
|
<line number="150" hits="0"/>
|
815
|
-
<line number="
|
816
|
-
<line number="
|
817
|
-
<line number="
|
818
|
-
<line number="
|
819
|
-
<line number="
|
820
|
-
<line number="
|
839
|
+
<line number="155" hits="0"/>
|
840
|
+
<line number="156" hits="0"/>
|
841
|
+
<line number="157" hits="0"/>
|
842
|
+
<line number="159" hits="0"/>
|
843
|
+
<line number="166" hits="0"/>
|
844
|
+
<line number="167" hits="0"/>
|
845
|
+
<line number="170" hits="0"/>
|
821
846
|
<line number="171" hits="0"/>
|
822
|
-
<line number="
|
823
|
-
<line number="
|
824
|
-
<line number="175" hits="0"/>
|
825
|
-
<line number="176" hits="0"/>
|
847
|
+
<line number="177" hits="0"/>
|
848
|
+
<line number="179" hits="0"/>
|
826
849
|
<line number="180" hits="0"/>
|
827
850
|
<line number="181" hits="0"/>
|
828
|
-
<line number="
|
829
|
-
<line number="184" hits="0"/>
|
830
|
-
<line number="185" hits="0"/>
|
851
|
+
<line number="182" hits="0"/>
|
831
852
|
<line number="186" hits="0"/>
|
832
853
|
<line number="187" hits="0"/>
|
833
854
|
<line number="189" hits="0"/>
|
834
855
|
<line number="190" hits="0"/>
|
856
|
+
<line number="191" hits="0"/>
|
857
|
+
<line number="192" hits="0"/>
|
835
858
|
<line number="193" hits="0"/>
|
859
|
+
<line number="195" hits="0"/>
|
836
860
|
<line number="196" hits="0"/>
|
837
|
-
<line number="197" hits="0"/>
|
838
861
|
<line number="199" hits="0"/>
|
839
|
-
<line number="200" hits="0"/>
|
840
|
-
<line number="201" hits="0"/>
|
841
862
|
<line number="202" hits="0"/>
|
842
863
|
<line number="203" hits="0"/>
|
843
864
|
<line number="205" hits="0"/>
|
@@ -845,7 +866,13 @@
|
|
845
866
|
<line number="207" hits="0"/>
|
846
867
|
<line number="208" hits="0"/>
|
847
868
|
<line number="209" hits="0"/>
|
869
|
+
<line number="211" hits="0"/>
|
870
|
+
<line number="212" hits="0"/>
|
871
|
+
<line number="213" hits="0"/>
|
872
|
+
<line number="214" hits="0"/>
|
848
873
|
<line number="216" hits="0"/>
|
874
|
+
<line number="221" hits="0"/>
|
875
|
+
<line number="228" hits="0"/>
|
849
876
|
</lines>
|
850
877
|
</class>
|
851
878
|
</classes>
|
@@ -5,7 +5,7 @@ import contextlib
|
|
5
5
|
from collections.abc import Callable
|
6
6
|
from pathlib import Path
|
7
7
|
|
8
|
-
from pdf_file_renamer.domain.models import FileRenameOperation
|
8
|
+
from pdf_file_renamer.domain.models import ConfidenceLevel, FileRenameOperation
|
9
9
|
from pdf_file_renamer.domain.ports import (
|
10
10
|
DOIExtractor,
|
11
11
|
FilenameGenerator,
|
@@ -103,12 +103,18 @@ class PDFRenameWorkflow:
|
|
103
103
|
|
104
104
|
# Mark complete
|
105
105
|
if status_callback:
|
106
|
+
# result.confidence is already a string due to use_enum_values=True
|
107
|
+
confidence_str = (
|
108
|
+
result.confidence.value
|
109
|
+
if isinstance(result.confidence, ConfidenceLevel)
|
110
|
+
else result.confidence
|
111
|
+
)
|
106
112
|
status_callback(
|
107
113
|
filename,
|
108
114
|
{
|
109
115
|
"status": "Complete",
|
110
116
|
"stage": "✓",
|
111
|
-
"confidence":
|
117
|
+
"confidence": confidence_str,
|
112
118
|
},
|
113
119
|
)
|
114
120
|
|
@@ -31,16 +31,14 @@ class PDF2DOIExtractor(DOIExtractor):
|
|
31
31
|
try:
|
32
32
|
# Run pdf2doi in executor to avoid blocking
|
33
33
|
loop = asyncio.get_event_loop()
|
34
|
-
|
34
|
+
result = await loop.run_in_executor(
|
35
35
|
None, pdf2doi.pdf2doi, str(pdf_path)
|
36
36
|
)
|
37
37
|
|
38
|
-
|
38
|
+
# pdf2doi returns a dict (not a list)
|
39
|
+
if not result or not isinstance(result, dict):
|
39
40
|
return None
|
40
41
|
|
41
|
-
# Get the first result
|
42
|
-
result = results[0]
|
43
|
-
|
44
42
|
# Check if DOI was found
|
45
43
|
identifier = result.get("identifier")
|
46
44
|
if not identifier:
|
@@ -50,15 +48,51 @@ class PDF2DOIExtractor(DOIExtractor):
|
|
50
48
|
if identifier_type.lower() not in ("doi", "arxiv"):
|
51
49
|
return None
|
52
50
|
|
53
|
-
# Extract metadata from validation_info (
|
51
|
+
# Extract metadata from validation_info (JSON string from CrossRef API)
|
54
52
|
validation_info = result.get("validation_info", "")
|
55
53
|
|
56
|
-
# Parse
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
54
|
+
# Parse JSON metadata
|
55
|
+
import json
|
56
|
+
|
57
|
+
metadata = {}
|
58
|
+
if validation_info:
|
59
|
+
try:
|
60
|
+
metadata = json.loads(validation_info)
|
61
|
+
except json.JSONDecodeError:
|
62
|
+
pass
|
63
|
+
|
64
|
+
# Extract title
|
65
|
+
title = metadata.get("title")
|
66
|
+
|
67
|
+
# Extract authors (list of dicts with 'given' and 'family' fields)
|
68
|
+
authors = None
|
69
|
+
if "author" in metadata:
|
70
|
+
author_list = metadata["author"]
|
71
|
+
authors = []
|
72
|
+
for author in author_list:
|
73
|
+
if isinstance(author, dict):
|
74
|
+
family = author.get("family", "")
|
75
|
+
given = author.get("given", "")
|
76
|
+
if family:
|
77
|
+
full_name = f"{given} {family}".strip() if given else family
|
78
|
+
authors.append(full_name)
|
79
|
+
if not authors:
|
80
|
+
authors = None
|
81
|
+
|
82
|
+
# Extract year from published-online or published
|
83
|
+
year = None
|
84
|
+
for date_field in ["published-online", "published", "created"]:
|
85
|
+
if date_field in metadata and "date-parts" in metadata[date_field]:
|
86
|
+
date_parts = metadata[date_field]["date-parts"]
|
87
|
+
if date_parts and len(date_parts) > 0 and len(date_parts[0]) > 0:
|
88
|
+
year = str(date_parts[0][0])
|
89
|
+
break
|
90
|
+
|
91
|
+
# Extract journal (container-title)
|
92
|
+
journal = metadata.get("container-title")
|
93
|
+
|
94
|
+
# Extract publisher
|
95
|
+
publisher = metadata.get("publisher")
|
62
96
|
|
63
97
|
return DOIMetadata(
|
64
98
|
doi=identifier,
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/presentation/formatters.py
RENAMED
@@ -7,7 +7,7 @@ from rich.prompt import Prompt
|
|
7
7
|
from rich.table import Table
|
8
8
|
from rich.text import Text
|
9
9
|
|
10
|
-
from pdf_file_renamer.domain.models import FileRenameOperation
|
10
|
+
from pdf_file_renamer.domain.models import ConfidenceLevel, FileRenameOperation
|
11
11
|
|
12
12
|
|
13
13
|
class ProgressDisplay:
|
@@ -146,7 +146,13 @@ class InteractivePrompt:
|
|
146
146
|
info_text.append("Suggested: ", style="bold green")
|
147
147
|
info_text.append(f"{operation.new_filename}\n", style="green")
|
148
148
|
info_text.append("Confidence: ", style="bold yellow")
|
149
|
-
|
149
|
+
# Handle both enum and string confidence
|
150
|
+
conf_str = (
|
151
|
+
operation.confidence.value
|
152
|
+
if isinstance(operation.confidence, ConfidenceLevel)
|
153
|
+
else operation.confidence
|
154
|
+
)
|
155
|
+
info_text.append(f"{conf_str}\n", style="yellow")
|
150
156
|
info_text.append("Reasoning: ", style="bold white")
|
151
157
|
info_text.append(operation.reasoning, style="dim white")
|
152
158
|
|
@@ -206,10 +212,16 @@ class ResultsTable:
|
|
206
212
|
reasoning = op.reasoning
|
207
213
|
if len(reasoning) > 100:
|
208
214
|
reasoning = reasoning[:100] + "..."
|
215
|
+
# Handle both enum and string confidence
|
216
|
+
conf_str = (
|
217
|
+
op.confidence.value
|
218
|
+
if isinstance(op.confidence, ConfidenceLevel)
|
219
|
+
else op.confidence
|
220
|
+
)
|
209
221
|
table.add_row(
|
210
222
|
op.original_path.name,
|
211
223
|
op.new_filename,
|
212
|
-
|
224
|
+
conf_str,
|
213
225
|
reasoning,
|
214
226
|
)
|
215
227
|
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/application/__init__.py
RENAMED
File without changes
|
File without changes
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/application/rename_service.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/__init__.py
RENAMED
File without changes
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/infrastructure/config.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/src/pdf_file_renamer/presentation/__init__.py
RENAMED
File without changes
|
File without changes
|
File without changes
|
{pdf_file_renamer-0.6.0 → pdf_file_renamer-0.6.1}/tests/data/2025-dennis-managing-complexity.pdf
RENAMED
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|