isitcredible 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.
- isitcredible-0.1.0/PKG-INFO +14 -0
- isitcredible-0.1.0/README.md +173 -0
- isitcredible-0.1.0/isitcredible/__init__.py +4 -0
- isitcredible-0.1.0/isitcredible/client.py +259 -0
- isitcredible-0.1.0/isitcredible.egg-info/PKG-INFO +14 -0
- isitcredible-0.1.0/isitcredible.egg-info/SOURCES.txt +9 -0
- isitcredible-0.1.0/isitcredible.egg-info/dependency_links.txt +1 -0
- isitcredible-0.1.0/isitcredible.egg-info/requires.txt +1 -0
- isitcredible-0.1.0/isitcredible.egg-info/top_level.txt +2 -0
- isitcredible-0.1.0/pyproject.toml +25 -0
- isitcredible-0.1.0/setup.cfg +4 -0
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: isitcredible
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the isitcredible.com academic peer-review API
|
|
5
|
+
Author: isitcredible.com
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://isitcredible.com
|
|
8
|
+
Project-URL: Documentation, https://isitcredible.com/docs/api
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Requires-Dist: requests>=2.28
|
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# isitcredible — Python SDK
|
|
2
|
+
|
|
3
|
+
Python client for the [isitcredible.com](https://isitcredible.com) automated peer-review API.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
pip install isitcredible
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Quick start
|
|
12
|
+
|
|
13
|
+
```python
|
|
14
|
+
from isitcredible import Client
|
|
15
|
+
|
|
16
|
+
client = Client("iic_your_api_key")
|
|
17
|
+
report = client.analyze("paper.pdf")
|
|
18
|
+
report.save("review.pdf")
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
`analyze()` submits the document and polls until the report is ready, then returns a `Report` object. **Jobs take at least 20 minutes and may run longer** — the default timeout is 60 minutes.
|
|
22
|
+
|
|
23
|
+
## API key
|
|
24
|
+
|
|
25
|
+
Generate a key from your [account page](https://isitcredible.com/account). Keys start with `iic_` and require a verified email address.
|
|
26
|
+
|
|
27
|
+
```python
|
|
28
|
+
client = Client("iic_your_api_key")
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
You can also read the key from an environment variable:
|
|
32
|
+
|
|
33
|
+
```python
|
|
34
|
+
import os
|
|
35
|
+
from isitcredible import Client
|
|
36
|
+
|
|
37
|
+
client = Client(os.environ["IIC_API_KEY"])
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
## Report types
|
|
41
|
+
|
|
42
|
+
| Mode | Price | Description |
|
|
43
|
+
|------|-------|-------------|
|
|
44
|
+
| `standard` | $5.00 | Full peer review: methodological critique, identified issues, directions for future research. |
|
|
45
|
+
| `extended` | $7.00 | Everything in *standard*, plus an editorial response note and a proofreading pass. |
|
|
46
|
+
|
|
47
|
+
```python
|
|
48
|
+
report = client.analyze("paper.pdf", mode="extended")
|
|
49
|
+
```
|
|
50
|
+
|
|
51
|
+
## Saving the report
|
|
52
|
+
|
|
53
|
+
```python
|
|
54
|
+
report.save("review.pdf") # PDF (default)
|
|
55
|
+
report.save("review.txt", format="txt") # plain text
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
Or get the raw bytes:
|
|
59
|
+
|
|
60
|
+
```python
|
|
61
|
+
pdf_bytes = report.download()
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
## Handling timeouts
|
|
65
|
+
|
|
66
|
+
Because jobs are long-running, `analyze()` (and `wait()`) will raise `JobTimeoutError` if the job doesn't finish within the timeout. The job **keeps running on the server** — you can resume polling using the `job_id` attached to the exception:
|
|
67
|
+
|
|
68
|
+
```python
|
|
69
|
+
from isitcredible import Client, JobTimeoutError
|
|
70
|
+
|
|
71
|
+
client = Client("iic_your_api_key")
|
|
72
|
+
|
|
73
|
+
try:
|
|
74
|
+
report = client.analyze("paper.pdf", timeout=3600) # 60 min
|
|
75
|
+
except JobTimeoutError as e:
|
|
76
|
+
print(f"Timed out. Job is still running: {e.job_id}")
|
|
77
|
+
# Resume later:
|
|
78
|
+
report = client.wait(e.job_id, timeout=3600)
|
|
79
|
+
report.save("review.pdf")
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
If you lose track of a job ID, use `list_jobs()` to find it:
|
|
83
|
+
|
|
84
|
+
```python
|
|
85
|
+
jobs = client.list_jobs()
|
|
86
|
+
# Each entry has 'uuid', 'status', 'title', 'mode', 'audit_date'
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
## Advanced: submit and poll separately
|
|
90
|
+
|
|
91
|
+
Use `submit()` and `wait()` directly if you need to fire-and-forget or manage polling yourself:
|
|
92
|
+
|
|
93
|
+
```python
|
|
94
|
+
# Submit without blocking
|
|
95
|
+
job = client.submit("paper.pdf", mode="standard")
|
|
96
|
+
job_id = job["job_id"]
|
|
97
|
+
print(f"Submitted: {job_id}")
|
|
98
|
+
|
|
99
|
+
# ... do other things ...
|
|
100
|
+
|
|
101
|
+
# Resume polling later
|
|
102
|
+
report = client.wait(job_id, poll_interval=60, timeout=7200)
|
|
103
|
+
report.save("review.pdf")
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
## Checking your balance
|
|
107
|
+
|
|
108
|
+
```python
|
|
109
|
+
balance = client.get_credits()
|
|
110
|
+
print(f"${balance['balance_usd']:.2f} remaining")
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
## Webhooks
|
|
114
|
+
|
|
115
|
+
Register a webhook to receive a POST when a job completes, instead of polling:
|
|
116
|
+
|
|
117
|
+
```python
|
|
118
|
+
# Register (secret is shown once — save it)
|
|
119
|
+
hook = client.create_webhook("https://yourapp.com/webhook")
|
|
120
|
+
print(hook["secret"])
|
|
121
|
+
|
|
122
|
+
# Or pass a webhook URL per job
|
|
123
|
+
client.submit("paper.pdf", webhook_url="https://yourapp.com/webhook")
|
|
124
|
+
|
|
125
|
+
# Manage webhooks
|
|
126
|
+
hooks = client.list_webhooks()
|
|
127
|
+
client.delete_webhook(hooks[0]["id"])
|
|
128
|
+
```
|
|
129
|
+
|
|
130
|
+
## Full method reference
|
|
131
|
+
|
|
132
|
+
| Method | Description |
|
|
133
|
+
|--------|-------------|
|
|
134
|
+
| `analyze(file_path, mode, note, webhook_url, poll_interval, timeout)` | Submit + poll + return `Report`. Blocks until complete. |
|
|
135
|
+
| `submit(file_path, mode, note, webhook_url)` | Submit without waiting. Returns `dict` with `job_id`. |
|
|
136
|
+
| `wait(job_id, poll_interval, timeout)` | Poll an existing job to completion. Returns `Report`. |
|
|
137
|
+
| `get_job(job_id)` | Get current status and metadata for a job. |
|
|
138
|
+
| `list_jobs()` | List your last 50 jobs. |
|
|
139
|
+
| `get_credits()` | Get your current credit balance. |
|
|
140
|
+
| `create_webhook(url, event)` | Register a webhook. Returns signing secret (shown once). |
|
|
141
|
+
| `list_webhooks()` | List registered webhooks. |
|
|
142
|
+
| `delete_webhook(id)` | Delete a webhook. |
|
|
143
|
+
|
|
144
|
+
### Report object
|
|
145
|
+
|
|
146
|
+
| Attribute | Description |
|
|
147
|
+
|-----------|-------------|
|
|
148
|
+
| `job_id` | Job UUID. |
|
|
149
|
+
| `status` | `completed` or `published`. |
|
|
150
|
+
| `mode` | `standard` or `extended`. |
|
|
151
|
+
| `title` | Paper title (extracted from document). |
|
|
152
|
+
| `authors` | Authors (extracted from document). |
|
|
153
|
+
| `discipline` | Academic discipline (extracted from document). |
|
|
154
|
+
| `report_url` | Direct URL to download the report. |
|
|
155
|
+
| `.download(format)` | Return report as bytes (`"pdf"` or `"txt"`). |
|
|
156
|
+
| `.save(path, format)` | Write report to a file. |
|
|
157
|
+
|
|
158
|
+
## Errors
|
|
159
|
+
|
|
160
|
+
| Exception | Description |
|
|
161
|
+
|-----------|-------------|
|
|
162
|
+
| `IsItCredibleError` | Base class. Has `.status_code` and `.detail`. |
|
|
163
|
+
| `JobTimeoutError` | Polling timed out. Has `.job_id` — use it to resume with `wait()`. |
|
|
164
|
+
|
|
165
|
+
HTTP errors map to `IsItCredibleError` with the relevant status code:
|
|
166
|
+
|
|
167
|
+
| Code | Meaning |
|
|
168
|
+
|------|---------|
|
|
169
|
+
| `401` | Missing or invalid API key. |
|
|
170
|
+
| `402` | Insufficient balance. |
|
|
171
|
+
| `403` | Email not verified. |
|
|
172
|
+
| `404` | Job not found. |
|
|
173
|
+
| `400` | Invalid input (file too large, wrong format, etc.). |
|
|
@@ -0,0 +1,259 @@
|
|
|
1
|
+
"""
|
|
2
|
+
isitcredible — Python SDK
|
|
3
|
+
~~~~~~~~~~~~~~~~~~~~~~~~~
|
|
4
|
+
|
|
5
|
+
Usage:
|
|
6
|
+
from isitcredible import Client
|
|
7
|
+
|
|
8
|
+
client = Client("iic_your_api_key")
|
|
9
|
+
report = client.analyze("paper.pdf")
|
|
10
|
+
report.save("review.pdf")
|
|
11
|
+
"""
|
|
12
|
+
import os
|
|
13
|
+
import time
|
|
14
|
+
from pathlib import Path
|
|
15
|
+
from typing import Optional, Union
|
|
16
|
+
|
|
17
|
+
import requests
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
API_BASE = "https://isitcredible.com/api/v1"
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
class IsItCredibleError(Exception):
|
|
24
|
+
"""Base exception for API errors."""
|
|
25
|
+
def __init__(self, message: str, status_code: int = None, detail: str = None):
|
|
26
|
+
self.status_code = status_code
|
|
27
|
+
self.detail = detail or message
|
|
28
|
+
super().__init__(message)
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
class JobTimeoutError(IsItCredibleError):
|
|
32
|
+
"""Raised when polling exceeds the timeout."""
|
|
33
|
+
pass
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
class Report:
|
|
37
|
+
"""Represents a completed analysis report."""
|
|
38
|
+
|
|
39
|
+
def __init__(self, job: dict, client: "Client"):
|
|
40
|
+
self.job_id: str = job["uuid"]
|
|
41
|
+
self.status: str = job["status"]
|
|
42
|
+
self.mode: str = job.get("mode", "standard")
|
|
43
|
+
self.title: str = job.get("title")
|
|
44
|
+
self.authors: str = job.get("authors")
|
|
45
|
+
self.discipline: str = job.get("discipline")
|
|
46
|
+
self.report_url: str = job.get("report_url")
|
|
47
|
+
self._client = client
|
|
48
|
+
|
|
49
|
+
def download(self, format: str = "pdf") -> bytes:
|
|
50
|
+
"""Download the report as bytes."""
|
|
51
|
+
if not self.report_url:
|
|
52
|
+
raise IsItCredibleError("No report available (job may not be completed).")
|
|
53
|
+
resp = self._client._get(f"/jobs/{self.job_id}/report", params={"format": format},
|
|
54
|
+
stream=True)
|
|
55
|
+
return resp.content
|
|
56
|
+
|
|
57
|
+
def save(self, path: Union[str, Path], format: str = "pdf"):
|
|
58
|
+
"""Download and save the report to a file."""
|
|
59
|
+
data = self.download(format=format)
|
|
60
|
+
Path(path).write_bytes(data)
|
|
61
|
+
|
|
62
|
+
def __repr__(self):
|
|
63
|
+
return f"<Report job_id={self.job_id!r} status={self.status!r} title={self.title!r}>"
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class Client:
|
|
67
|
+
"""
|
|
68
|
+
isitcredible.com API client.
|
|
69
|
+
|
|
70
|
+
Args:
|
|
71
|
+
api_key: Your API key (starts with ``iic_``).
|
|
72
|
+
base_url: Override the API base URL (for testing).
|
|
73
|
+
timeout: HTTP request timeout in seconds.
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __init__(
|
|
77
|
+
self,
|
|
78
|
+
api_key: str,
|
|
79
|
+
base_url: str = None,
|
|
80
|
+
timeout: int = 30,
|
|
81
|
+
):
|
|
82
|
+
if not api_key:
|
|
83
|
+
raise IsItCredibleError("API key is required.")
|
|
84
|
+
self._api_key = api_key
|
|
85
|
+
self._base_url = (base_url or API_BASE).rstrip("/")
|
|
86
|
+
self._timeout = timeout
|
|
87
|
+
self._session = requests.Session()
|
|
88
|
+
self._session.headers.update({
|
|
89
|
+
"Authorization": f"Bearer {api_key}",
|
|
90
|
+
"User-Agent": "isitcredible-python/0.1.0",
|
|
91
|
+
})
|
|
92
|
+
|
|
93
|
+
# -----------------------------------------------------------------
|
|
94
|
+
# Core high-level method
|
|
95
|
+
# -----------------------------------------------------------------
|
|
96
|
+
|
|
97
|
+
def analyze(
|
|
98
|
+
self,
|
|
99
|
+
file_path: Union[str, Path],
|
|
100
|
+
mode: str = "standard",
|
|
101
|
+
note: str = "",
|
|
102
|
+
webhook_url: str = "",
|
|
103
|
+
poll_interval: int = 15,
|
|
104
|
+
timeout: int = 3600,
|
|
105
|
+
) -> Report:
|
|
106
|
+
"""
|
|
107
|
+
Submit a document for analysis and wait for the result.
|
|
108
|
+
|
|
109
|
+
Args:
|
|
110
|
+
file_path: Path to the PDF, TXT, or MD file.
|
|
111
|
+
mode: ``"standard"`` or ``"extended"``.
|
|
112
|
+
note: Optional note for the reviewer.
|
|
113
|
+
webhook_url: Optional URL to receive a POST when the job completes.
|
|
114
|
+
poll_interval: Seconds between status checks (default 15).
|
|
115
|
+
timeout: Maximum seconds to wait (default 3600 = 60 min).
|
|
116
|
+
|
|
117
|
+
Returns:
|
|
118
|
+
A :class:`Report` object with the completed analysis.
|
|
119
|
+
|
|
120
|
+
Raises:
|
|
121
|
+
IsItCredibleError: On API errors.
|
|
122
|
+
JobTimeoutError: If the job doesn't finish within ``timeout``.
|
|
123
|
+
FileNotFoundError: If ``file_path`` doesn't exist.
|
|
124
|
+
"""
|
|
125
|
+
job = self.submit(file_path, mode=mode, note=note, webhook_url=webhook_url)
|
|
126
|
+
job_id = job["job_id"]
|
|
127
|
+
return self.wait(job_id, poll_interval=poll_interval, timeout=timeout)
|
|
128
|
+
|
|
129
|
+
# -----------------------------------------------------------------
|
|
130
|
+
# Low-level methods (for advanced users / async pipelines)
|
|
131
|
+
# -----------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
def submit(
|
|
134
|
+
self,
|
|
135
|
+
file_path: Union[str, Path],
|
|
136
|
+
mode: str = "standard",
|
|
137
|
+
note: str = "",
|
|
138
|
+
webhook_url: str = "",
|
|
139
|
+
) -> dict:
|
|
140
|
+
"""
|
|
141
|
+
Submit a file for analysis without waiting.
|
|
142
|
+
|
|
143
|
+
Returns:
|
|
144
|
+
dict with ``job_id``, ``status``, ``mode``, ``message``.
|
|
145
|
+
"""
|
|
146
|
+
file_path = Path(file_path)
|
|
147
|
+
if not file_path.exists():
|
|
148
|
+
raise FileNotFoundError(f"File not found: {file_path}")
|
|
149
|
+
|
|
150
|
+
with open(file_path, "rb") as f:
|
|
151
|
+
data = {"mode": mode, "user_note": note}
|
|
152
|
+
if webhook_url:
|
|
153
|
+
data["webhook_url"] = webhook_url
|
|
154
|
+
resp = self._post(
|
|
155
|
+
"/jobs",
|
|
156
|
+
files={"main_file": (file_path.name, f)},
|
|
157
|
+
data=data,
|
|
158
|
+
)
|
|
159
|
+
return resp.json()
|
|
160
|
+
|
|
161
|
+
def wait(self, job_id: str, poll_interval: int = 15, timeout: int = 3600) -> Report:
|
|
162
|
+
"""
|
|
163
|
+
Poll a job until completion.
|
|
164
|
+
|
|
165
|
+
Args:
|
|
166
|
+
job_id: The job UUID returned by :meth:`submit`.
|
|
167
|
+
poll_interval: Seconds between polls.
|
|
168
|
+
timeout: Maximum wait time in seconds.
|
|
169
|
+
|
|
170
|
+
Returns:
|
|
171
|
+
A :class:`Report` object.
|
|
172
|
+
"""
|
|
173
|
+
deadline = time.time() + timeout
|
|
174
|
+
|
|
175
|
+
while True:
|
|
176
|
+
job = self.get_job(job_id)
|
|
177
|
+
status = job.get("status", "")
|
|
178
|
+
|
|
179
|
+
if status in ("completed", "published"):
|
|
180
|
+
return Report(job, self)
|
|
181
|
+
|
|
182
|
+
if status == "failed":
|
|
183
|
+
raise IsItCredibleError(
|
|
184
|
+
f"Job {job_id} failed.",
|
|
185
|
+
detail=job.get("admin_notes", ""),
|
|
186
|
+
)
|
|
187
|
+
|
|
188
|
+
if time.time() > deadline:
|
|
189
|
+
err = JobTimeoutError(
|
|
190
|
+
f"Job {job_id} did not complete within {timeout}s (status: {status})."
|
|
191
|
+
)
|
|
192
|
+
err.job_id = job_id
|
|
193
|
+
raise err
|
|
194
|
+
|
|
195
|
+
time.sleep(poll_interval)
|
|
196
|
+
|
|
197
|
+
def get_job(self, job_id: str) -> dict:
|
|
198
|
+
"""Get status and metadata for a single job."""
|
|
199
|
+
return self._get(f"/jobs/{job_id}").json()
|
|
200
|
+
|
|
201
|
+
def list_jobs(self) -> list:
|
|
202
|
+
"""List your recent jobs."""
|
|
203
|
+
return self._get("/jobs").json()
|
|
204
|
+
|
|
205
|
+
def get_credits(self) -> dict:
|
|
206
|
+
"""Get your current credit balance."""
|
|
207
|
+
return self._get("/credits").json()
|
|
208
|
+
|
|
209
|
+
# -- Webhook management --
|
|
210
|
+
|
|
211
|
+
def create_webhook(self, url: str, event: str = "job.completed") -> dict:
|
|
212
|
+
"""Register a default webhook URL. Returns the signing secret (save it!)."""
|
|
213
|
+
return self._post("/webhooks", data={"url": url, "event": event}).json()
|
|
214
|
+
|
|
215
|
+
def list_webhooks(self) -> list:
|
|
216
|
+
"""List your registered webhooks."""
|
|
217
|
+
return self._get("/webhooks").json()
|
|
218
|
+
|
|
219
|
+
def delete_webhook(self, webhook_id: int) -> dict:
|
|
220
|
+
"""Delete a webhook by ID."""
|
|
221
|
+
return self._delete(f"/webhooks/{webhook_id}").json()
|
|
222
|
+
|
|
223
|
+
# -----------------------------------------------------------------
|
|
224
|
+
# HTTP helpers
|
|
225
|
+
# -----------------------------------------------------------------
|
|
226
|
+
|
|
227
|
+
def _get(self, path: str, params: dict = None, stream: bool = False) -> requests.Response:
|
|
228
|
+
resp = self._session.get(
|
|
229
|
+
f"{self._base_url}{path}",
|
|
230
|
+
params=params,
|
|
231
|
+
timeout=self._timeout,
|
|
232
|
+
stream=stream,
|
|
233
|
+
)
|
|
234
|
+
self._check(resp)
|
|
235
|
+
return resp
|
|
236
|
+
|
|
237
|
+
def _post(self, path: str, **kwargs) -> requests.Response:
|
|
238
|
+
kwargs.setdefault("timeout", self._timeout)
|
|
239
|
+
resp = self._session.post(f"{self._base_url}{path}", **kwargs)
|
|
240
|
+
self._check(resp)
|
|
241
|
+
return resp
|
|
242
|
+
|
|
243
|
+
def _delete(self, path: str) -> requests.Response:
|
|
244
|
+
resp = self._session.delete(f"{self._base_url}{path}", timeout=self._timeout)
|
|
245
|
+
self._check(resp)
|
|
246
|
+
return resp
|
|
247
|
+
|
|
248
|
+
@staticmethod
|
|
249
|
+
def _check(resp: requests.Response):
|
|
250
|
+
if resp.status_code >= 400:
|
|
251
|
+
try:
|
|
252
|
+
detail = resp.json().get("detail", resp.text)
|
|
253
|
+
except Exception:
|
|
254
|
+
detail = resp.text
|
|
255
|
+
raise IsItCredibleError(
|
|
256
|
+
f"HTTP {resp.status_code}: {detail}",
|
|
257
|
+
status_code=resp.status_code,
|
|
258
|
+
detail=detail,
|
|
259
|
+
)
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: isitcredible
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Python SDK for the isitcredible.com academic peer-review API
|
|
5
|
+
Author: isitcredible.com
|
|
6
|
+
License: MIT
|
|
7
|
+
Project-URL: Homepage, https://isitcredible.com
|
|
8
|
+
Project-URL: Documentation, https://isitcredible.com/docs/api
|
|
9
|
+
Classifier: Development Status :: 4 - Beta
|
|
10
|
+
Classifier: Intended Audience :: Science/Research
|
|
11
|
+
Classifier: Topic :: Scientific/Engineering
|
|
12
|
+
Classifier: Programming Language :: Python :: 3
|
|
13
|
+
Requires-Python: >=3.8
|
|
14
|
+
Requires-Dist: requests>=2.28
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
README.md
|
|
2
|
+
pyproject.toml
|
|
3
|
+
isitcredible/__init__.py
|
|
4
|
+
isitcredible/client.py
|
|
5
|
+
isitcredible.egg-info/PKG-INFO
|
|
6
|
+
isitcredible.egg-info/SOURCES.txt
|
|
7
|
+
isitcredible.egg-info/dependency_links.txt
|
|
8
|
+
isitcredible.egg-info/requires.txt
|
|
9
|
+
isitcredible.egg-info/top_level.txt
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
requests>=2.28
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=68.0", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "isitcredible"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Python SDK for the isitcredible.com academic peer-review API"
|
|
9
|
+
requires-python = ">=3.8"
|
|
10
|
+
license = {text = "MIT"}
|
|
11
|
+
authors = [{name = "isitcredible.com"}]
|
|
12
|
+
dependencies = ["requests>=2.28"]
|
|
13
|
+
classifiers = [
|
|
14
|
+
"Development Status :: 4 - Beta",
|
|
15
|
+
"Intended Audience :: Science/Research",
|
|
16
|
+
"Topic :: Scientific/Engineering",
|
|
17
|
+
"Programming Language :: Python :: 3",
|
|
18
|
+
]
|
|
19
|
+
|
|
20
|
+
[project.urls]
|
|
21
|
+
Homepage = "https://isitcredible.com"
|
|
22
|
+
Documentation = "https://isitcredible.com/docs/api"
|
|
23
|
+
|
|
24
|
+
[tool.setuptools.packages.find]
|
|
25
|
+
where = ["."]
|