Skip to content

Commit 6899a18

Browse files
Add Python API usage examples (issue #25) (#50)
* Add Python API usage examples for journal assessment - Create examples/ directory with standalone demonstration scripts - Add basic_assessment.py: single journal and batch assessment examples - Add bibtex_processing.py: BibTeX file processing and result aggregation - Add comprehensive README.md with setup instructions and usage guidance Addresses issue #25: enhances JOSS submission and improves developer onboarding * Add SPDX license identifiers to example files Fixes quality check failures by adding required MIT license headers to both Python example files. [AI-assisted] * Fix API usage in example files - Fix import in basic_assessment.py to use dispatcher.query_dispatcher - Fix bibtex_processing.py to use correct result attributes (insufficient_data_count instead of unknown_count, assessment_results instead of entries, is_retracted instead of retracted) - Both examples now execute successfully and demonstrate the API correctly [AI-assisted] * Add example execution validation to quality checks and CI/CD - Create check-examples.py script to validate all example files execute successfully - Add example execution check to run-quality-checks.sh script - Add example execution step to CI/CD pipeline - Fix API usage in example files: - Fix import in basic_assessment.py to use dispatcher.query_dispatcher - Fix bibtex_processing.py to use correct result attributes - All examples now execute successfully and are validated in CI/CD This ensures the Python API examples provided for JOSS remain functional and serve as reliable documentation for users. [AI-assisted] * Address PR review comments for examples README Changes based on review feedback: 1. Fix setup requirements - make sync mandatory, config optional (displays config, doesn't configure) 2. Add sync step to download backend data before running examples 3. Update expected outputs to indicate they may vary based on enabled backends 4. Fix configuration section to correctly describe precedence (local .aletheia-probe first) 5. Remove Support section as requested 6. Add reference to main configuration documentation All review comments addressed and replied to on GitHub. [AI-assisted] --------- Co-authored-by: florath-ai-assistant[bot] <Andreas.Florath@telekom.de>
1 parent ac623cd commit 6899a18

File tree

6 files changed

+407
-0
lines changed

6 files changed

+407
-0
lines changed

.github/workflows/ci.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ jobs:
5555
run: |
5656
python scripts/check-logging.py
5757
58+
- name: Check example execution
59+
run: |
60+
python scripts/check-examples.py
61+
5862
test:
5963
name: Tests
6064
runs-on: ubuntu-latest

examples/README.md

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
# Aletheia Probe Python API Examples
2+
3+
This directory contains standalone Python scripts demonstrating how to use the Aletheia Probe Python API for journal assessment.
4+
5+
## Setup Requirements
6+
7+
Before running the examples, ensure you have:
8+
9+
1. **Installed Aletheia Probe:**
10+
```bash
11+
pip install aletheia-probe
12+
```
13+
14+
2. **Synced backend data:**
15+
```bash
16+
aletheia-probe sync
17+
```
18+
This downloads the predatory journal lists and other data sources needed for assessment.
19+
20+
3. **(Optional) View configuration:**
21+
```bash
22+
aletheia-probe config
23+
```
24+
This displays the current configuration. The tool works with default settings, but you can customize backends and other options.
25+
26+
## Examples
27+
28+
### basic_assessment.py
29+
30+
Demonstrates core journal assessment functionality:
31+
32+
- **Single journal assessment** - Assess one journal with detailed results
33+
- **Batch assessment** - Process multiple journals efficiently
34+
- **Result interpretation** - How to work with assessment results
35+
36+
**Usage:**
37+
```bash
38+
python basic_assessment.py
39+
```
40+
41+
**Expected Output (similar to):**
42+
```
43+
=== Single Journal Assessment ===
44+
Journal: Nature Communications
45+
Assessment: legitimate
46+
Confidence: 98%
47+
Backend Results: 13 sources checked
48+
49+
=== Batch Assessment ===
50+
Science: legitimate (98% confidence)
51+
PLOS ONE: legitimate (100% confidence)
52+
Journal of Biomedicine: legitimate (83% confidence)
53+
```
54+
55+
*Note: Results may vary based on enabled backends and available data.*
56+
57+
### bibtex_processing.py
58+
59+
Shows how to process BibTeX bibliography files:
60+
61+
- **BibTeX file parsing** - Extract journals from bibliography files
62+
- **Batch journal assessment** - Assess all journals in a bibliography
63+
- **Result aggregation** - Summarize findings and generate reports
64+
65+
**Usage:**
66+
```bash
67+
python bibtex_processing.py
68+
```
69+
70+
**Expected Output (similar to):**
71+
```
72+
=== BibTeX File Processing ===
73+
Created sample BibTeX file: /tmp/tmplbecdqnw.bib
74+
75+
=== Assessment Summary ===
76+
Total entries processed: 3
77+
Legitimate journals: 2
78+
Predatory journals: 1
79+
Insufficient data: 0
80+
81+
=== Detailed Results ===
82+
Journal: Nature Communications
83+
Assessment: legitimate
84+
Confidence: 93%
85+
Risk Level: LOW - Safe to publish
86+
```
87+
88+
*Note: Results may vary based on enabled backends and available data.*
89+
90+
## Integration Tips
91+
92+
### Error Handling
93+
94+
Always wrap API calls in try-catch blocks:
95+
96+
```python
97+
try:
98+
result = await query_dispatcher.assess_journal(query)
99+
# Process result...
100+
except Exception as e:
101+
print(f"Assessment failed: {e}")
102+
```
103+
104+
### Configuration
105+
106+
The API uses configuration in this order of precedence:
107+
1. Local `.aletheia-probe/` directory (project-specific settings)
108+
2. User configuration directory (`~/.config/aletheia-probe/` or platform equivalent)
109+
3. Default settings
110+
111+
For more details, see the [Configuration documentation](https://github.com/sustainet-guardian/aletheia-probe#configuration).
112+
113+
### Async/Await
114+
115+
All assessment functions are asynchronous. Use within async functions or with `asyncio.run()`:
116+
117+
```python
118+
import asyncio
119+
120+
async def main():
121+
result = await query_dispatcher.assess_journal(query)
122+
return result
123+
124+
# Run the async function
125+
result = asyncio.run(main())
126+
```

examples/basic_assessment.py

Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: MIT
3+
"""
4+
Basic journal assessment examples using the Aletheia Probe Python API.
5+
6+
This script demonstrates:
7+
1. Single journal assessment
8+
2. Batch assessment of multiple journals
9+
3. Result interpretation examples
10+
"""
11+
12+
import asyncio
13+
from aletheia_probe.dispatcher import query_dispatcher
14+
from aletheia_probe.models import QueryInput
15+
16+
17+
async def single_assessment():
18+
"""Assess a single journal and interpret results."""
19+
print("=== Single Journal Assessment ===")
20+
21+
# Create query for Nature Communications
22+
query = QueryInput(
23+
raw_input="Nature Communications",
24+
normalized_name="nature communications",
25+
identifiers={"issn": "2041-1723"}
26+
)
27+
28+
# Perform assessment
29+
result = await query_dispatcher.assess_journal(query)
30+
31+
# Display results
32+
print(f"Journal: {query.raw_input}")
33+
print(f"Assessment: {result.assessment}")
34+
print(f"Confidence: {result.confidence:.0%}")
35+
print(f"Backend Results: {len(result.backend_results)} sources checked")
36+
37+
return result
38+
39+
40+
async def batch_assessment():
41+
"""Assess multiple journals in batch."""
42+
print("\n=== Batch Assessment ===")
43+
44+
# List of journals to assess
45+
journals = [
46+
{"name": "Science", "issn": "1095-9203"},
47+
{"name": "PLOS ONE", "issn": "1932-6203"},
48+
{"name": "Journal of Biomedicine", "issn": None} # Potentially suspicious
49+
]
50+
51+
results = []
52+
53+
for journal in journals:
54+
query = QueryInput(
55+
raw_input=journal["name"],
56+
normalized_name=journal["name"].lower(),
57+
identifiers={"issn": journal["issn"]} if journal["issn"] else {}
58+
)
59+
60+
result = await query_dispatcher.assess_journal(query)
61+
results.append((journal["name"], result))
62+
63+
print(f"{journal['name']}: {result.assessment} ({result.confidence:.0%} confidence)")
64+
65+
return results
66+
67+
68+
async def main():
69+
"""Run all examples."""
70+
try:
71+
# Single assessment
72+
await single_assessment()
73+
74+
# Batch assessment
75+
await batch_assessment()
76+
77+
print("\n=== Assessment Complete ===")
78+
79+
except Exception as e:
80+
print(f"Error: {e}")
81+
82+
83+
if __name__ == "__main__":
84+
asyncio.run(main())

examples/bibtex_processing.py

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
#!/usr/bin/env python3
2+
# SPDX-License-Identifier: MIT
3+
"""
4+
BibTeX processing examples using the Aletheia Probe Python API.
5+
6+
This script demonstrates:
7+
1. BibTeX file processing
8+
2. Journal extraction and assessment
9+
3. Result aggregation and reporting
10+
"""
11+
12+
import asyncio
13+
import tempfile
14+
from pathlib import Path
15+
from aletheia_probe.batch_assessor import BibtexBatchAssessor
16+
17+
18+
def create_sample_bibtex():
19+
"""Create a sample BibTeX file for demonstration."""
20+
bibtex_content = """
21+
@article{smith2023nature,
22+
title={A groundbreaking study},
23+
author={Smith, John},
24+
journal={Nature Communications},
25+
volume={14},
26+
year={2023},
27+
issn={2041-1723}
28+
}
29+
30+
@article{doe2023plos,
31+
title={Another important study},
32+
author={Doe, Jane},
33+
journal={PLOS ONE},
34+
volume={18},
35+
year={2023},
36+
issn={1932-6203}
37+
}
38+
39+
@article{unknown2023suspicious,
40+
title={Suspicious research},
41+
author={Unknown, Author},
42+
journal={International Journal of Advanced Research},
43+
volume={1},
44+
year={2023}
45+
}
46+
"""
47+
48+
# Create temporary file
49+
temp_file = tempfile.NamedTemporaryFile(mode='w', suffix='.bib', delete=False)
50+
temp_file.write(bibtex_content)
51+
temp_file.close()
52+
53+
return Path(temp_file.name)
54+
55+
56+
async def process_bibtex_file():
57+
"""Process a BibTeX file and assess all journals."""
58+
print("=== BibTeX File Processing ===")
59+
60+
# Create sample BibTeX file
61+
bibtex_path = create_sample_bibtex()
62+
print(f"Created sample BibTeX file: {bibtex_path}")
63+
64+
try:
65+
# Initialize the batch assessor
66+
assessor = BibtexBatchAssessor()
67+
68+
# Process the BibTeX file
69+
result = await assessor.assess_bibtex_file(bibtex_path, verbose=True)
70+
71+
# Display summary results
72+
print(f"\n=== Assessment Summary ===")
73+
print(f"Total entries processed: {result.total_entries}")
74+
print(f"Legitimate journals: {result.legitimate_count}")
75+
print(f"Predatory journals: {result.predatory_count}")
76+
print(f"Insufficient data: {result.insufficient_data_count}")
77+
78+
return result
79+
80+
finally:
81+
# Clean up temporary file
82+
bibtex_path.unlink()
83+
84+
85+
async def analyze_results(result):
86+
"""Analyze and display detailed results."""
87+
print("\n=== Detailed Results ===")
88+
89+
for bibtex_entry, assessment in result.assessment_results:
90+
print(f"\nJournal: {bibtex_entry.journal_name}")
91+
print(f" Assessment: {assessment.assessment}")
92+
print(f" Confidence: {assessment.confidence:.0%}")
93+
94+
if bibtex_entry.is_retracted:
95+
print(f" Warning: Contains retracted articles")
96+
97+
if assessment.assessment == "predatory":
98+
print(f" Risk Level: HIGH - Avoid this journal")
99+
elif assessment.assessment == "legitimate":
100+
print(f" Risk Level: LOW - Safe to publish")
101+
else:
102+
print(f" Risk Level: UNKNOWN - Requires manual review")
103+
104+
105+
async def main():
106+
"""Run all examples."""
107+
try:
108+
# Process BibTeX file
109+
result = await process_bibtex_file()
110+
111+
# Analyze results
112+
await analyze_results(result)
113+
114+
print("\n=== Processing Complete ===")
115+
116+
except Exception as e:
117+
print(f"Error: {e}")
118+
119+
120+
if __name__ == "__main__":
121+
asyncio.run(main())

0 commit comments

Comments
 (0)