ipaapi 1.0.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.
- ipaapi-1.0.0/.gitignore +11 -0
- ipaapi-1.0.0/CHANGELOG.md +345 -0
- ipaapi-1.0.0/LICENSE +21 -0
- ipaapi-1.0.0/PKG-INFO +833 -0
- ipaapi-1.0.0/README.md +784 -0
- ipaapi-1.0.0/examples/probe_geneidtype.py +166 -0
- ipaapi-1.0.0/examples/probe_interpret.py +99 -0
- ipaapi-1.0.0/examples/quickstart.py +117 -0
- ipaapi-1.0.0/ipaapi-1.0.0-py3-none-any.whl +0 -0
- ipaapi-1.0.0/pyproject.toml +50 -0
- ipaapi-1.0.0/src/ipaapi/__init__.py +92 -0
- ipaapi-1.0.0/src/ipaapi/_payload.py +150 -0
- ipaapi-1.0.0/src/ipaapi/auth.py +575 -0
- ipaapi-1.0.0/src/ipaapi/cli.py +971 -0
- ipaapi-1.0.0/src/ipaapi/client.py +658 -0
- ipaapi-1.0.0/src/ipaapi/dataset.py +285 -0
- ipaapi-1.0.0/src/ipaapi/errors.py +101 -0
- ipaapi-1.0.0/src/ipaapi/history.py +145 -0
- ipaapi-1.0.0/src/ipaapi/mapping.py +485 -0
- ipaapi-1.0.0/src/ipaapi/models.py +193 -0
- ipaapi-1.0.0/src/ipaapi/triage.py +136 -0
- ipaapi-1.0.0/tests/conftest.py +66 -0
- ipaapi-1.0.0/tests/test_auth.py +150 -0
- ipaapi-1.0.0/tests/test_batch.py +135 -0
- ipaapi-1.0.0/tests/test_cli.py +292 -0
- ipaapi-1.0.0/tests/test_client.py +57 -0
- ipaapi-1.0.0/tests/test_history.py +143 -0
- ipaapi-1.0.0/tests/test_mapping.py +203 -0
- ipaapi-1.0.0/tests/test_payload.py +175 -0
- ipaapi-1.0.0/tests/test_skiprows.py +148 -0
- ipaapi-1.0.0/tests/test_triage.py +461 -0
ipaapi-1.0.0/.gitignore
ADDED
|
@@ -0,0 +1,345 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
Versions follow [semantic versioning](https://semver.org): breaking changes to
|
|
4
|
+
the command line or the Python API bump the major number, additions bump the
|
|
5
|
+
minor, fixes bump the patch.
|
|
6
|
+
|
|
7
|
+
Check what you're running with `ipaapi --version`, which reports the version,
|
|
8
|
+
the install location, and whether it's an editable checkout rather than a wheel.
|
|
9
|
+
|
|
10
|
+
## 1.0.0 — 2026-08-05
|
|
11
|
+
|
|
12
|
+
First stable release. No code changes from 0.5.0 — the version marks that the
|
|
13
|
+
interface is settled and the package has been used in earnest.
|
|
14
|
+
|
|
15
|
+
Established in production: 37 analyses submitted against live IPA across 5
|
|
16
|
+
donors and 9 cell types, with batch submission, quota-aware resume and the
|
|
17
|
+
identifier/measurement vocabulary all exercised.
|
|
18
|
+
|
|
19
|
+
From here, breaking changes to the CLI or the Python API require a major
|
|
20
|
+
version bump.
|
|
21
|
+
|
|
22
|
+
### Interface considered stable
|
|
23
|
+
|
|
24
|
+
- `ipaapi validate | submit | status | report | history` and their flags.
|
|
25
|
+
- `ColumnMapping`, `Observation`, `Measurement`, `Dataset`, `IPAClient`.
|
|
26
|
+
- `MeasurementType`, `AnalysisStatus`, `ReferenceSet`, `GENE_ID_TYPES`.
|
|
27
|
+
- The exception hierarchy under `IPAError`.
|
|
28
|
+
- The submission log format (tab-separated, header row, append-only).
|
|
29
|
+
|
|
30
|
+
## 0.5.0 — 2026-08-05
|
|
31
|
+
|
|
32
|
+
### Changed
|
|
33
|
+
|
|
34
|
+
- **Released under the MIT licence.** `pyproject.toml` previously declared
|
|
35
|
+
`Proprietary` with no `LICENSE` file present — a combination that, on a public
|
|
36
|
+
repository, legally means nobody may use it. Adds `LICENSE`, the OSI
|
|
37
|
+
classifier, and supported-Python classifiers.
|
|
38
|
+
- Package description rewritten to say what the tool does and what distinguishes
|
|
39
|
+
it, and to stop advertising result retrieval, which needs a commercial add-on.
|
|
40
|
+
- README gains Contributing and Licence sections, and a Status section listing
|
|
41
|
+
the known open questions rather than leaving them implicit.
|
|
42
|
+
|
|
43
|
+
## 0.4.1 — 2026-08-05
|
|
44
|
+
|
|
45
|
+
### Documentation
|
|
46
|
+
|
|
47
|
+
- **Extended README**, structured as a manual: quick start, full CLI reference,
|
|
48
|
+
recipes, a section on the undocumented parts of IPA, authentication including
|
|
49
|
+
headless use, Python API, troubleshooting table, and the wire format.
|
|
50
|
+
- **Corrected again — the reference-set size rule does not hold in practice.**
|
|
51
|
+
0.4.0 reported §4.1.3.1's rule (ipkb below 2000 identifiers, dataset at 2000
|
|
52
|
+
or more) as fact. Checked against 37 completed analyses of 1,804–6,245
|
|
53
|
+
identifiers, *all* were scored against "Ingenuity Knowledge Base (Genes
|
|
54
|
+
Only)". The documented rule is therefore not predictive; set
|
|
55
|
+
`--reference-set` explicitly for anything you intend to compare.
|
|
56
|
+
|
|
57
|
+
## 0.4.0 — 2026-08-05
|
|
58
|
+
|
|
59
|
+
Working from QIAGEN's official *IPA Integration Module (APIs)* documentation
|
|
60
|
+
(April 2026) rather than from inference. Several things we had established by
|
|
61
|
+
trial were confirmed; two were wrong.
|
|
62
|
+
|
|
63
|
+
### Added
|
|
64
|
+
|
|
65
|
+
- **`GENE_ID_TYPES`** — all 33 documented `geneidtype` values with the database
|
|
66
|
+
each refers to (§3.1), exposed as `ipaapi submit --list-id-types`. A value
|
|
67
|
+
outside the list is warned about, with a near-match suggestion, but still
|
|
68
|
+
sent; IPA remains the authority.
|
|
69
|
+
- **Species is carried by the identifier type**, not a separate parameter:
|
|
70
|
+
`hugo` human, `mousesymeg` mouse, `ratsymeg` rat. There is no species
|
|
71
|
+
argument in the API — an open question now closed.
|
|
72
|
+
- **`ReferenceSet.IPKB`** (`ipkb`), the Ingenuity Knowledge Base.
|
|
73
|
+
|
|
74
|
+
### Changed
|
|
75
|
+
|
|
76
|
+
- **Corrected: omitting `referenceset` does not mean "use the Knowledge
|
|
77
|
+
Base".** IPA chooses by dataset size — `ipkb` below 2000 identifiers,
|
|
78
|
+
`dataset` at 2000 or more (§4.1.3.1). Large pre-filtered hit lists therefore
|
|
79
|
+
get their own genes as the background even with the parameter omitted. Pass
|
|
80
|
+
`--reference-set ipkb` explicitly to override.
|
|
81
|
+
|
|
82
|
+
### Notes
|
|
83
|
+
|
|
84
|
+
- The measurement types and ranges this package enforces match §3.1 exactly.
|
|
85
|
+
- §3.1 also states that **out-of-range expression values are silently ignored**
|
|
86
|
+
— "analysis will still proceed without errors or warning diagnostics", with
|
|
87
|
+
offending entries dropped. That makes the range check load-bearing rather
|
|
88
|
+
than pedantic: declaring log2 values as `foldchange` would have silently
|
|
89
|
+
discarded every gene between -1 and 1.
|
|
90
|
+
|
|
91
|
+
## 0.3.3 — 2026-08-05
|
|
92
|
+
|
|
93
|
+
### Added
|
|
94
|
+
|
|
95
|
+
- **`examples/probe_geneidtype.py` can now enumerate the accepted gene ID
|
|
96
|
+
vocabulary for free.** IPA has no endpoint that lists it, but the failure
|
|
97
|
+
modes are distinguishable: an unknown type is rejected before any analysis is
|
|
98
|
+
created, while a *valid* type gets as far as creating one and only then hits
|
|
99
|
+
the allowance. So when the account is quota-blocked, every accepted type
|
|
100
|
+
reports itself at no cost. The script detects this automatically — it
|
|
101
|
+
continues past acceptances that were blocked by the allowance, and stops
|
|
102
|
+
immediately if a candidate genuinely creates an analysis, so an account with
|
|
103
|
+
allowance remaining is never drained.
|
|
104
|
+
|
|
105
|
+
## 0.3.2 — 2026-08-05
|
|
106
|
+
|
|
107
|
+
### Changed
|
|
108
|
+
|
|
109
|
+
- **The allowance rejection is confirmed**: `Unable to run analysis: Analysis
|
|
110
|
+
limit exceeded`, delivered as an HTML page. Added verbatim to
|
|
111
|
+
`QUOTA_PATTERNS` and documented; the remaining patterns stay as guesses at
|
|
112
|
+
other phrasings.
|
|
113
|
+
- Page chrome ("About QIAGEN Bioinformatics | Contact Us (c)2000-2026 ...") is
|
|
114
|
+
stripped along with the support boilerplate, so the message reads as just
|
|
115
|
+
the reason.
|
|
116
|
+
|
|
117
|
+
## 0.3.1 — 2026-08-05
|
|
118
|
+
|
|
119
|
+
### Fixed
|
|
120
|
+
|
|
121
|
+
- **Error pages were truncated exactly where the reason lives.** IPA opens its
|
|
122
|
+
error pages with support boilerplate and puts the actual message last; the
|
|
123
|
+
page text was clipped at 300 characters from the front, so a real failure
|
|
124
|
+
read `Unable to run analysis: Analysis ` and stopped. The boilerplate is now
|
|
125
|
+
stripped and the tail preserved.
|
|
126
|
+
- **"No files were moved" was printed even when files had been moved.** A
|
|
127
|
+
mid-batch failure files everything submitted before it; the message now says
|
|
128
|
+
what actually happened.
|
|
129
|
+
- **"Unable to run analysis" was misreported as a parameter error.** That
|
|
130
|
+
wording means the request reached IPA's analysis logic, so it is not a
|
|
131
|
+
malformed request. New `AnalysisRefusedError` says so, and the run stops and
|
|
132
|
+
leaves the remaining files in place — the right behaviour if the cause is an
|
|
133
|
+
allowance or capacity limit.
|
|
134
|
+
- **A quota message delivered as an HTML page** was classified as a bad
|
|
135
|
+
parameter. Quota detection now runs against the whole body before the HTML
|
|
136
|
+
branch.
|
|
137
|
+
|
|
138
|
+
## 0.3.0 — 2026-08-05
|
|
139
|
+
|
|
140
|
+
Everything needed for a correct analysis is now established and defaulted.
|
|
141
|
+
Confirmed working end to end against live IPA: `hugo` identifiers, `logratio`
|
|
142
|
+
fold changes, no `referenceset` — producing populated p-values and FDR.
|
|
143
|
+
|
|
144
|
+
### Changed — breaking
|
|
145
|
+
|
|
146
|
+
- **`referenceset` is no longer sent by default.** QIAGEN's demo sent
|
|
147
|
+
`referenceset=dataset`, and this package inherited it unexamined. That makes
|
|
148
|
+
the background the uploaded genes, which for a pre-filtered hit list is the
|
|
149
|
+
same set as the foreground — leaving the enrichment statistics degenerate:
|
|
150
|
+
z-scores produced, p-values and FDR absent. Omitting the parameter lets IPA
|
|
151
|
+
apply its own default, which is confirmed to produce real statistics.
|
|
152
|
+
|
|
153
|
+
`IPAClient.submit(reference_set=...)` now defaults to `None`, and
|
|
154
|
+
`--reference-set` defaults to `omit`. Pass `dataset` explicitly to restore
|
|
155
|
+
the old behaviour — appropriate only when uploading a complete measured
|
|
156
|
+
transcriptome.
|
|
157
|
+
|
|
158
|
+
## 0.2.7 — 2026-08-05
|
|
159
|
+
|
|
160
|
+
### Added
|
|
161
|
+
|
|
162
|
+
- **`hugo` confirmed as a gene ID type** for human gene symbols, verified
|
|
163
|
+
against the live API. `CONFIRMED_ID_TYPES` is now `("ensembl", "hugo")`.
|
|
164
|
+
Of the three names in the desktop client's label "Gene Symbol - human
|
|
165
|
+
(HUGO / HGNC / Entrez Gene)", only the first is accepted — `genesymbol` and
|
|
166
|
+
`Gene Symbol` are both rejected.
|
|
167
|
+
- README documents the confirmed vocabulary, since QIAGEN does not.
|
|
168
|
+
|
|
169
|
+
## 0.2.6 — 2026-08-05
|
|
170
|
+
|
|
171
|
+
### Changed
|
|
172
|
+
|
|
173
|
+
- **Rejection messages lead with what was rejected.** The explanation used to
|
|
174
|
+
come first and the actual cause several lines down, which is easy to skim
|
|
175
|
+
past and read as success. The first line is now
|
|
176
|
+
`REJECTED: IPA does not recognise the gene ID type 'X'.`, followed by
|
|
177
|
+
`NOTHING WAS SUBMITTED.`, with the reasoning below that.
|
|
178
|
+
- Recorded that `Gene Symbol` is rejected as well as `genesymbol` — so the API
|
|
179
|
+
does not take the desktop client's display label either.
|
|
180
|
+
|
|
181
|
+
## 0.2.5 — 2026-08-05
|
|
182
|
+
|
|
183
|
+
### Changed
|
|
184
|
+
|
|
185
|
+
- Gene ID type candidates reordered from evidence rather than convention. The
|
|
186
|
+
IPA desktop client labels a gene symbol column "Gene Symbol - human (HUGO /
|
|
187
|
+
HGNC / Entrez Gene)", so `symbol`, `hugo`, `hgnc` and `entrezgene` are tried
|
|
188
|
+
first. Still guesses — the client and the REST API need not share vocabulary
|
|
189
|
+
— but guesses taken from IPA's own wording.
|
|
190
|
+
|
|
191
|
+
## 0.2.4 — 2026-08-05
|
|
192
|
+
|
|
193
|
+
### Fixed
|
|
194
|
+
|
|
195
|
+
- **Stopped advertising unverified gene ID types.** The help text listed nine
|
|
196
|
+
"common" identifier types that were guesses. `genesymbol` is among the ones
|
|
197
|
+
IPA rejects — "Unknown GeneId Type (genesymbol)" — so the list sent users
|
|
198
|
+
straight into a failed submission. Only `ensembl` is confirmed, and
|
|
199
|
+
`CONFIRMED_ID_TYPES` now holds only values observed to work.
|
|
200
|
+
|
|
201
|
+
### Added
|
|
202
|
+
|
|
203
|
+
- **An unrecognised gene ID type is named and explained.** IPA identifies the
|
|
204
|
+
value it rejected in its error page; the message now quotes it, points at the
|
|
205
|
+
`--ID` flag specifically rather than offering a list of suspects, and notes
|
|
206
|
+
that probing costs allowance whenever a candidate is *accepted*.
|
|
207
|
+
- `examples/probe_geneidtype.py` tries candidate type strings against a
|
|
208
|
+
two-row extract and stops at the first IPA accepts.
|
|
209
|
+
|
|
210
|
+
## 0.2.3 — 2026-08-05
|
|
211
|
+
|
|
212
|
+
### Fixed
|
|
213
|
+
|
|
214
|
+
- **A mapping that fails every file no longer quarantines the directory.** If
|
|
215
|
+
no file validates, the fault is the command rather than the data, so nothing
|
|
216
|
+
is moved to `failed/` and the run says so. Files only get filed when *some*
|
|
217
|
+
succeed and others don't.
|
|
218
|
+
|
|
219
|
+
### Added
|
|
220
|
+
|
|
221
|
+
- **Fold-change rejections suggest `logratio` when the data is log-scaled.**
|
|
222
|
+
A column named "Fold_change" may hold either linear ratios or log2 values.
|
|
223
|
+
When values declared `foldchange` cluster inside (-1, 1) — where fold change
|
|
224
|
+
cannot go but a log ratio spends most of its time — the error now names
|
|
225
|
+
`logratio` as the likely fix instead of only reporting the rejection.
|
|
226
|
+
|
|
227
|
+
## 0.2.2 — 2026-08-05
|
|
228
|
+
|
|
229
|
+
### Added
|
|
230
|
+
|
|
231
|
+
- **Warns when a column declared `logratio` looks like signed fold change.**
|
|
232
|
+
A real log ratio is centred on zero, so its distribution always contains
|
|
233
|
+
values between -1 and 1. Signed fold change (`ratio` if >= 1, else
|
|
234
|
+
`-1/ratio`) can contain none, by construction. A `logratio` column with
|
|
235
|
+
nothing in that interval is therefore almost certainly fold change
|
|
236
|
+
mislabelled — which IPA reads as `2^value`, inflating every magnitude while
|
|
237
|
+
leaving directions intact. Warning only, and skipped below 50 values.
|
|
238
|
+
|
|
239
|
+
## 0.2.1 — 2026-08-05
|
|
240
|
+
|
|
241
|
+
### Fixed
|
|
242
|
+
|
|
243
|
+
- **A rejected parameter no longer quarantines good files.** IPA answers a
|
|
244
|
+
malformed request with an HTML error page; that was being treated as a
|
|
245
|
+
per-file failure, so a bad `--reference-set` moved a perfectly good file into
|
|
246
|
+
`failed/`. An HTML response is now `MalformedRequestError`: the run stops, no
|
|
247
|
+
file is moved, and the message names the likely parameters and quotes what
|
|
248
|
+
the page said.
|
|
249
|
+
- Identifier warnings were printed twice per dataset.
|
|
250
|
+
|
|
251
|
+
### Changed
|
|
252
|
+
|
|
253
|
+
- **Removed `--reference-set ingenuity`.** It was a guess and IPA rejects it.
|
|
254
|
+
- **Added `--reference-set omit`**, which leaves the parameter out of the
|
|
255
|
+
request entirely so IPA applies its own default. For pre-filtered hit lists
|
|
256
|
+
`dataset` makes the background equal the analysis-ready set, which degenerates
|
|
257
|
+
the enrichment statistics — z-scores are still produced but overlap p-values
|
|
258
|
+
are not meaningful.
|
|
259
|
+
- Interpret-link failures report the URL, the response body and the JSON keys
|
|
260
|
+
rather than just the status code.
|
|
261
|
+
|
|
262
|
+
## 0.2.0 — 2026-08-05
|
|
263
|
+
|
|
264
|
+
First version used against live IPA. Everything below came out of that run.
|
|
265
|
+
|
|
266
|
+
### Added
|
|
267
|
+
|
|
268
|
+
- **Command line.** `ipaapi` console script with `validate`, `submit`,
|
|
269
|
+
`status`, `report` and `history` subcommands.
|
|
270
|
+
- `--ID COLUMN:TYPE` and `--FC COLUMN:TYPE[:CUTOFF]`, column positions 0-based.
|
|
271
|
+
- `--ID` may be given twice: the second identifier fills rows where the
|
|
272
|
+
primary is blank.
|
|
273
|
+
- **Batch submission.** `PATH` may be a directory; `--pattern` selects files by
|
|
274
|
+
substring or glob, `--recursive` descends. One dataset and analysis per file.
|
|
275
|
+
- **File triage.** Directory submits move each file as its outcome is known:
|
|
276
|
+
`submitted/` when IPA accepts it, `failed/` (with a `.error.txt` note) when
|
|
277
|
+
the file is at fault, left in place when the allowance is exhausted. Those
|
|
278
|
+
folders are excluded from discovery, so a re-run resumes exactly where it
|
|
279
|
+
stopped.
|
|
280
|
+
- **Quota detection.** `QuotaExceededError`, raised on HTTP 429 or when the
|
|
281
|
+
response matches `client.QUOTA_PATTERNS`, so an exhausted allowance is not
|
|
282
|
+
mistaken for a broken file. Heuristic — IPA's wording is undocumented, and
|
|
283
|
+
the raw response body is always reported.
|
|
284
|
+
- **Submission log.** Every analysis appends a timestamped row to
|
|
285
|
+
`~/.local/state/ipaapi/submissions.tsv`; `ipaapi history` reads it back with
|
|
286
|
+
`--project`, `--since`, `--limit` and `--status`. IPA's API cannot enumerate
|
|
287
|
+
analyses, so without this a lost terminal means a lost ID.
|
|
288
|
+
- **Token refresh.** An expired cached token is renewed from its refresh token
|
|
289
|
+
over HTTP, with no browser and no prompt. Makes headless and copied-token
|
|
290
|
+
workflows self-sustaining. `--token-file` points at a cache copied from
|
|
291
|
+
another machine.
|
|
292
|
+
- `IPAAPI_TOKEN_FILE` and `IPAAPI_LOG_FILE` environment variables, for hosts
|
|
293
|
+
where the home directory isn't writable. An unwritable token cache means a
|
|
294
|
+
fresh login on every run, so both failures now say how to fix them.
|
|
295
|
+
- `--skip-rows N` for files with a comment or title line above the header.
|
|
296
|
+
- `--browser NAME`, and a login failure message that distinguishes `DISPLAY`
|
|
297
|
+
unset from no browser found, pointing at `ssh -X` or a port forward.
|
|
298
|
+
|
|
299
|
+
### Changed
|
|
300
|
+
|
|
301
|
+
- **`submit` no longer waits by default.** It returns once the analyses are
|
|
302
|
+
queued and prints the `status`/`report` commands; `--wait` restores polling.
|
|
303
|
+
`--no-wait` is still accepted so existing commands keep working.
|
|
304
|
+
- Observation and dataset names come from the filename rather than the
|
|
305
|
+
fold-change column header, so a batch doesn't produce analyses all named
|
|
306
|
+
"log2FC".
|
|
307
|
+
- Directory submits validate per file; a malformed file goes to `failed/`
|
|
308
|
+
instead of aborting the batch. `validate` remains all-or-nothing.
|
|
309
|
+
|
|
310
|
+
### Fixed
|
|
311
|
+
|
|
312
|
+
- **Delimiter sniffing read line 1 rather than the header**, so a comment line
|
|
313
|
+
containing commas caused the whole file to be parsed as CSV — silently, with
|
|
314
|
+
the comment becoming the column names. A header that looks like a comment is
|
|
315
|
+
now rejected with an explanation.
|
|
316
|
+
- **`report` on an unfinished analysis** reported a bare HTTP 500. It now
|
|
317
|
+
checks status first and says the analysis is still running.
|
|
318
|
+
- **Token cache write failures were swallowed**, which looked identical to a
|
|
319
|
+
token expiring instantly.
|
|
320
|
+
|
|
321
|
+
## 0.1.0 — 2026-08-05
|
|
322
|
+
|
|
323
|
+
Initial package, built on QIAGEN's `python-api-demo` example code.
|
|
324
|
+
|
|
325
|
+
### Added
|
|
326
|
+
|
|
327
|
+
- `ColumnMapping` / `Observation` / `Measurement`: columns addressed by name in
|
|
328
|
+
any order, validated against the data before upload, replacing the demo's
|
|
329
|
+
fixed positional layout. `ColumnMapping.from_blocks()` reproduces the old
|
|
330
|
+
behaviour for migration.
|
|
331
|
+
- `IPAClient` with `submit`, `status`, `wait_for`, `results` and `report_url`.
|
|
332
|
+
- OAuth 2.0 + PKCE login with a disk token cache.
|
|
333
|
+
- Typed exception hierarchy under `IPAError`.
|
|
334
|
+
|
|
335
|
+
### Fixed relative to the demo
|
|
336
|
+
|
|
337
|
+
- **Request bodies are percent-encoded.** The demo concatenated them by hand,
|
|
338
|
+
so any value containing a space, `&`, `=`, `+` or `%` corrupted the request —
|
|
339
|
+
including the `Group Max Intensity` column in the demo's own sample dataset.
|
|
340
|
+
- OAuth no longer spins a CPU core waiting for the callback, validates the
|
|
341
|
+
`state` parameter, times out, shuts its server down, and handles an error
|
|
342
|
+
redirect instead of waiting forever.
|
|
343
|
+
- Submissions are never retried automatically, since a retried POST could
|
|
344
|
+
create duplicate analyses. GETs retry with backoff.
|
|
345
|
+
- Access tokens are excluded from `repr()`.
|
ipaapi-1.0.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ken Jones
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|